问题描述:给定一个图求最小生成树
思路: K r u s k a l算法每次选择n- 1条边,
所使用的贪婪准则是:
从剩下的边中选择一条不会产生环路的具有
最小耗费的边加入已选择的边的集合中。
注意到所选取的边若产生环路则不可能形成一棵生成树。
K r u s k a l算法分e 步,其中e 是网络中边的数目。
按耗费递增的顺序来考虑这e 条边,每次考虑一条边。
当考虑某条边时,若将其加入到已选边的集合中会出现环路,
则将其抛弃,否则,将它选入。
利用并查集的求法判断是否会构成回路:若他们根节点不同则不会有环
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Edge{
int a,b;
int cost;
}edge[505*505/2];
int father[505];
int d[505];
int v,e;
int cmp(Edge x,Edge y){
return x.cost<y.cost;
}
int ifind(int x){
if(x==father[x])
return x;
father[x]=ifind(father[x]);
return father[x];
}
int Union(int x,int y){
int f1=ifind(x);
int f2=ifind(y);
if(f1==f2)
return false;
if(f1>f2)
f2[father]=f1;
else
f1[father]=f2;
}
int kurukal(){
int sum=0;
for(int i=1;i<=v;i++)
father[i]=i;
sort(edge+1,edge+e+1,cmp);
for(int i=1;i<=e;i++){
if(Union(edge[i].a,edge[i].b)){
sum+=edge[i].cost;
}
}
return sum;
}
int main(){
int test;
scanf("%d",&test);
while(test--){
scanf("%d%d",&v,&e);
for(int i=1;i<=e;i++){
scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].cost);
}
for(int i=0;i<v;i++){
scanf("%d",&d[i]);
}
sort(d,d+v);
printf("%d\n",kurukal()+d[0]);
}
}
题目链接/*问题描述:给定一个图求最小生成树思路: K r u s k a l算法每次选择n- 1条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合中。注意到所选取的边若产生环路则不可能形成一棵生成树。K r u s k a l算法分e 步,其中e 是网络中边的数目。按耗费递增的顺序来考虑这e 条边,每次考虑一条边。当考虑某条边时,若将