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 }
原文地址:https://www.cnblogs.com/wally/p/2976709.html