hdu 1879 继续畅通工程

跟前几题畅通工程类似,求最小生成树。当状态是已修建时,直接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;
}

你可能感兴趣的:(hdu 1879 继续畅通工程)