hdu 4514(并查集判环)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514
Tencent昨天比赛的题目,昨天看的时候没什么思路,今天在网上搜了一下,说是可以用并查集做。。。果然,过了。。。看来还是做的题不够多啊!!!
思路:并查集判环,并把每次的边权值都加到根结点的上去,最后求每个根结点权值的最大值就行了。。。orz
View Code
1 #include<iostream> 2 #include<cstring> 3 const int N=100007; 4 using namespace std; 5 struct Edge{ 6 int u,v,w; 7 }edge[N*10]; 8 int parent[N]; 9 int weight[N]; 10 int n,m; 11 12 //初始化 13 void UFset(){ 14 memset(weight,0,sizeof(weight)); 15 for(int i=1;i<=n;i++){ 16 parent[i]=-1; 17 } 18 } 19 20 int Find(int x){ 21 int s; 22 //查找位置 23 for(s=x;parent[s]>=0;s=parent[s]) 24 ; 25 //优化,路径压缩,使后续的查找加速 26 while(s!=x){ 27 int tmp=parent[x]; 28 parent[x]=s; 29 x=tmp; 30 } 31 return s; 32 } 33 34 void Union(int R1,int R2,int w){ 35 int r1=Find(R1),r2=Find(R2);//r1为R1的根节点,r2为R2的根节点 36 int tmp=parent[r1]+parent[r2];//两个集合节点的个数之和(负数) 37 //如果R2所在的树结点个数大于R1所在的树节点个数 38 if(parent[r1]>parent[r2]){ //优化方案,加权法则 39 parent[r1]=r2; 40 parent[r2]=tmp; 41 weight[r2]+=w;//根结点权值 42 }else { 43 parent[r2]=r1; 44 parent[r1]=tmp; 45 weight[r1]+=w; 46 } 47 } 48 49 int main(){ 50 while(~scanf("%d%d",&n,&m)){ 51 UFset(); 52 bool tag=false; 53 for(int i=0;i<m;i++){ 54 scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); 55 if(Find(edge[i].u)!=Find(edge[i].v)){ 56 Union(edge[i].u,edge[i].v,edge[i].w); 57 }else { 58 tag=true; 59 } 60 } 61 if(tag){ 62 printf("YES\n"); 63 }else { 64 int ans=0; 65 for(int i=1;i<=n;i++){ 66 ans=max(ans,weight[i]); 67 } 68 printf("%d\n",ans); 69 } 70 } 71 return 0; 72 }