题目1028:继续畅通工程
本题是并查集的变形,即 开始时已有部分村庄是有路的,把他们设置为连通的,然后对所有边排序后
并逐个扫描,若不连通则累加上这条路的花费,把他们置为连通。
/*
*/
#include <stdio.h>
#include<algorithm>
using namespace std;
int parent[110],cnt,n,sum; //注意一定要全局变量,不要在主函数中重新定义。。
struct E{
int a;
int b;
int c; //建成a到b的路的花费
bool d; //标记路是否建成
bool operator < (const E &q) const{ //注意返回值的类型,运算符重载。
return c<q.c;
}
}r[5100];
void init()
{
cnt=0;sum=0;
int i;
for(i=0;i<=n;i++) //结点下标从1开始取到n;
parent[i]=-1;
}
int findRoot(int tmp)
{
if(parent[tmp]==-1)
return tmp;
else{
int tmpRoot=findRoot(parent[tmp]);
parent[tmp]=tmpRoot;
return tmpRoot;
}
}
int main()
{
int m,i,tmpA,tmpB;
//freopen("G:\\in.txt","r",stdin);
while(scanf("%d",&n)!=EOF){
if(n==0) break;
init();
m=n*(n-1)/2;
for(i=0;i<m;i++){
scanf("%d%d%d%d",&r[i].a,&r[i].b,&r[i].c,&r[i].d); //输入别忘了&!!!
if(r[i].d==1){
tmpA=findRoot(r[i].a),tmpB=findRoot(r[i].b);
if(tmpA!=tmpB) //根据并查集原理,要判断是否连通-------------------要点!!!
parent[tmpA]=tmpB;
}
}
sort(r,r+m);
for(i=0;i<m;i++){
tmpA=findRoot(r[i].a);tmpB=findRoot(r[i].b);
if(tmpA!=tmpB){
parent[tmpA]=tmpB;
sum+=r[i].c;
}
}
printf("%d\n",sum);
}
return 0;
}