跟前几题畅通工程类似,求最小生成树。当状态是已修建时,直接merge。值得注意的是得用scanf,用cin会超时。还得用路径压缩的并查集,不然也会TLE。
#include<iostream>
#include<algorithm>
using namespace std;//20:07
#define NUM 102
struct points
{
int start;
int end;
int w;
}pos[5050];
int set[NUM];
void init()
{
for(int i=0;i<NUM;++i)
set[i]=i;
}
int find(int x)
{
int r=x;
while(r!=set[r])
r=set[r];
return r;
}
int find2(int x)//带路径压缩的查找(非递归版)
{
int k, j, r;
r = x;
while(r != set[r]) //查找根节点
r = set[r]; //找到根节点,用r记录下
k = x;
while(k != r) //非递归路径压缩操作
{
j = set[k]; //用j暂存set[k]的父节点
set[k] = r; //set[x]指向根节点
k = j; //k移到父节点
}
return r; //返回根节点的值
}
void merge(int x,int y)
{
int a=find2(x);
int b=find2(y);
if(a!=b)
set[a]=b;
return;
}
int cmp(struct points a,struct points b)
{
return a.w < b.w;
}
int main()
{
int n,i,m,index,x,y,weight,status,sum;
freopen("C:\\Documents and Settings\\Administrator\\桌面\\input.txt","r",stdin);
//while(cin>>n&&n!=0){
while(scanf("%d",&n)!=EOF&&n!=0){
m=n*(n-1)/2;
index=0;
sum=0;
init();
while(m--){
cin>>x>>y>>weight>>status;
if(status==1)
merge(x,y);
else {
pos[index].start=x;
pos[index].end=y;
pos[index].w=weight;
++index;
}
}
sort(pos,pos+index,cmp);
for(i=0;i<index;++i){
if(find2(pos[i].start)!=find2(pos[i].end)){
merge(pos[i].start,pos[i].end);
sum+=pos[i].w;
}
}
//cout<<sum<<endl;
printf("%d\n",sum);
}
return 0;
}