文章标题 HDU 3371 : Connect the Cities(最小生成树--Kruskal+并查集)

本文介绍了一个基于最小生成树的问题背景及解决思路,通过Kruskal算法实现城市间的最优连接方案,确保所有城市能够以最低成本相互连接。

Connect the Cities

Description

In 2100, since the sea level rise, most of the cities disappear. Though some survived cities are still connected with others, but most of them become disconnected. The government wants to build some roads to connect all of these cities again, but they don’t want to take too much money.

Input

The first line contains the number of test cases.
Each test case starts with three integers: n, m and k. n (3 <= n <=500) stands for the number of survived cities, m (0 <= m <= 25000) stands for the number of roads you can choose to connect the cities and k (0 <= k <= 100) stands for the number of still connected cities.
To make it easy, the cities are signed from 1 to n.
Then follow m lines, each contains three integers p, q and c (0 <= c <= 1000), means it takes c to connect p and q.
Then follow k lines, each line starts with an integer t (2 <= t <= n) stands for the number of this connected cities. Then t integers follow stands for the id of these cities.

Output

For each case, output the least money you need to take, if it’s impossible, just output -1.

Sample Input

1
6 4 3
1 4 2
2 6 1
2 3 5
3 4 33
2 1 2
2 1 3
3 4 5 6

Sample Output

1
题意:由于海平面上升,一些城市被淹没了,但剩下来的城市有些还有保持联系,但大部分失去了联系。现要将所有的城市都能联系起来,但想花费最少的金钱。输入n,m,k,表示现有n个城市,然后m表示有m条路径可以建立,p和q连接需要花费c的金钱。然后接下来的k行,每一行中第一个数表示接下来的t个城市还保持着联系。最后要求出总共最少需要多少金钱将所有城市联系起来,如果不能联系起来输出-1。
分析:很明显这是最小生成树的题,用Kruskal算法,首先将已经联系的城市联系起来,算出已经有多少条边已经建立起来,然后将m条边排一下序,从花费最小的往里加,当刚好有n-1条边建立的时候说明城市已经联系起来了。最后判断一下是不是只有一颗树。
代码:

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<vector>
#include<math.h>
#include<map>
#include<queue> 
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
int n,m,k;
struct node {
    int x,y,cost;
};
node a[25005];
bool cmp(node a,node b){//按花费小的排序
    return a.cost < b.cost;
}
int con[505];
int fa[25005];
void init (){//初始化
    for (int i=1;i<=n;i++){
        fa[i]=i;
    }
}
int find(int x){
    return fa[x]==x?x:fa[x]=find (fa[x]);
}
int main ()
{
    int t;
    scanf ("%d",&t);
    while (t--){
        int cnt=0;
        scanf ("%d%d%d",&n,&m,&k);
        init();
        for (int i=0;i<m;i++){
            scanf ("%d%d%d",&a[i].x,&a[i].y,&a[i].cost);
        }
        int sum;
        for (int i=0;i<k;i++){
            scanf ("%d",&sum);
            for (int j=0;j<sum;j++){//将原先保持联系的城市建立起来
                scanf ("%d",&con[j]);
                if (j==0)continue;
                int fu=find(con[j-1]);
                int fv=find(con[j]);
                if (fu!=fv){
                    cnt++;//边数加一
                    fa[fu]=fv;
                }
            }
        }
        sort(a,a+m,cmp);//排序,然后往里加
        long long ans=0;
        for(int i=0;i<m;i++){
            int f1=find(a[i].x);
            int f2=find(a[i].y);
            if (f1!=f2){
                ans+=a[i].cost;
                fa[f1]=f2;
                cnt++;
            }
            if (cnt==n-1)break;
        } 
        int flag=1;
        int count=0;
        if (cnt<n-1)flag=0;//如果边数小于n-1,说明没发将n个城市建立联系
        if (flag){
            printf ("%lld\n",ans);
        }
        else {
            printf ("-1\n");
        }
    }
    return 0;
}
内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值