HDU-1856-More is better (并查集)
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1856
程序分析:
一个老板要完成一个项目,需要一些人来帮忙,越多越好,但是有个条件,这些人都应该彼此认识(直接跟间接),有个隐含的是如果没人可以帮忙,只好自己上阵,干活的就只有自己一个了。输入的是一对一对的朋友,他们都彼此认识。人数可以达到一千万(10000000)。
解决方法:
并查集可以解决,都是把认识的挂同一棵树上,最后统计那棵树最多人,结果就是这棵树的人数了。由于n巨大,所以需要对输入的人编号进行标记(0/-1),还有统计输入的人里面编号最大的那个。只有在下面循环统计最大树时速度才能加快。开数组时要注意,必须开比一千万大一点,但是只能开两个这样的数组,因为开到第三个时内存以经超过题目要求了,就是这里我WA了好几次内存超的。在编写并查集初始化函数时里面的for循环里的 i 不能 等于 Max,这样会跑到不是你申请的内存里初始化,虽然编译器不会报错,但是属于访问非法内存,这个问题还是让我WA了无数次后才发现。最后也没什么特别要注意的了。看代码吧。属于简单并查集题,陷阱可能就是输入0时要输出 1 吧。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 const long Max = 10000000+10; 6 long Far[Max]; 7 //long Rank[Max]; //这个数组不能在开了,开了就爆内存咯 8 long Num[Max]; 9 10 void Make_set(long n) 11 { 12 long i; 13 for(i=0; i<n; i++) //不能是i<=n , 会跑到不是你申请的内存里去初始化,这个问题是最后才发现的 14 { 15 Far[i] = i; 16 } 17 //memset(Rank, 0, sizeof(Rank)); 18 memset(Num, -1, sizeof(Num)); //把所有人的数量都初始化为-1,表示未存在,下面如果有输入时就标记为0 19 } 20 21 long Find(long x) 22 { 23 if(Far[x] != x) 24 return Far[x] = Find(Far[x]); 25 return x; 26 } 27 28 void Unio(long a, long b) 29 { 30 a = Find(a); 31 b = Find(b); 32 if(a == b) 33 return ; 34 Far[a] = b; 35 36 // 木有开Rank数组,只好全部默认把a挂在b树上 37 38 /*if(Rank[a] < Rank[b]) 39 Far[a] = b; 40 else if(Rank[a] > Rank[b]) 41 Far[b] = a; 42 else 43 { 44 Far[a] = b; 45 Rank[b]++; 46 }*/ 47 } 48 49 int main() 50 { 51 long n; 52 while(scanf("%ld", &n) != EOF) 53 { 54 if(n == 0) //输入n为0时,应该就是表示木有人可以帮忙,只好亲自上阵了吧, 55 //那么干活的就只有自己一个了,老板嘛,有人帮忙自己就不会去做的 56 { 57 cout<<1<<endl; 58 continue; 59 } 60 Make_set(Max); 61 long Num_max = 0; 62 for(long i=0; i<n; i++) 63 { 64 long a, b; 65 scanf("%ld%ld", &a, &b); 66 Num[a] = Num[b] = 0; //把有的人都标记为0 67 Num_max = Num_max > (a>b?a:b) ? Num_max:(a>b?a:b); //记录下最大的人编号,在下面找老大时可以减少一些判断 68 Unio(a, b); 69 70 } 71 long max = 0; 72 for(long j=1; j<=Num_max; j++) 73 { 74 if(Num[j] >= 0) //不小于0就表示存在于这些树里 75 { 76 Num[Find(j)]++; //以Find(j)为老大的树的结点加一 77 if(Num[Far[j]] > max) 78 max = Num[Far[j]]; //统计最大结点数量的树 79 } 80 } 81 printf("%ld\n", max); 82 } 83 return 0; 84 }