Kraskal算法
1.初始所有节点都独立
2.按照边的权值递增遍历所有的边,若遍历到的边上的两个点,分属在不同的集合,则这条边就是最小生成树上的一条边,并将这两个顶点合并。
3.如果出现集合数量只为1个,说明最小生成树已经构成。如果遍历完所有的边,集合还大于1个,说明原图不连通,最小生成树不存在。
代码
/* 题目描述: 省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。 输入: 测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。 当N为0时输入结束。 输出: 每个测试用例的输出占一行,输出全省畅通需要的最低成本。 样例输入: 3 1 2 1 0 1 3 2 0 2 3 4 0 3 1 2 1 0 1 3 2 0 2 3 4 1 3 1 2 1 0 1 3 2 1 2 3 4 1 0 样例输出: 3 1 0 */
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct edge{
int a , b ,cost;
bool operator < (const edge b)const{
return cost<b.cost;
}
}e[100*99/2];
int Tree[100],nodecount,ans;
int findRoot(int a){
if(Tree[a]==-1){
return a;
}
int root = findRoot(Tree[a]);
Tree[a] = root;
return root;
}
void unit(edge e){
int a_root = findRoot(e.a);
int b_root = findRoot(e.b);
if(a_root!=b_root){
Tree[a_root] = b_root;
ans += e.cost;
nodecount --;
}
}
int main(){
int N,a,b,cost,status;
while(cin>>N&&N){
nodecount = N;
ans = 0;
for(int i=1;i<=N;i++){
Tree[i]=-1;
}
int M = N*(N-1)/2;
for(int j=0;j<M;j++){
cin>>a>>b>>cost>>status;
e[j].a = a;
e[j].b = b;
if(status)
e[j].cost = 0;
else
e[j].cost = cost;
}
sort(e,e+M);
for(int m=0;m<M;m++){
unit(e[m]);
if(nodecount==1)
break;
}
printf("%d\n",ans);
}
return 0;
}