Description
Input
Output
Sample Input
4 1 2 3 4 5 6 1 6 4 1 2 3 4 5 6 7 8
Sample Output
4 2
Hint
A and B are friends(direct or indirect), B and C are friends(direct or indirect), then A and C are also friends(indirect). In the first sample {1,2,5,6} is the result. In the second sample {1,2},{3,4},{5,6},{7,8} are four kinds of answers.
题意:老师要选人去XXX,然后希望同学们都可以拉自己的关系去,最后需要计算某 个集合中最多的人数,这个理解了半天,现在把题中给的两组数据解释一下; PS:当不选的时候是1;
样例1:1-2;3-4;5-6;1-6 ; 所以 1 、 2 、 5 、 6 是关系好的同学,
所以有两个集合, {1,2,5,6}和{3,4};而前者元素多,是四个;
样例2: 1-2;3-4;5-6;7-8;
{1,2},{3,4},{5,6},{7,8};
比较后发现都是两个, 所以输出2 ;
题解:首先是并查集的套路, 找到父节点和子节点的关系;合并集合
结点信息是1,而不是初始化为0;
额外操作就是将父节点算到子节点里面,合并元素个数;
然后再遍历子节点所包含的元素个数 就可以了;
我直接按题中给的最大值暴力搞了,竟然AC了;
优化思路:找到最大结点,则遍历从这里开始;
AC代码;(极限数据) PS 优化代码在下面;
#include <bits/stdc++.h> using namespace std ; int vis[10000000+50],pre[10000000+50],ans , m , n ; int find(int x ) { if(x!=pre[x]) return pre[x]=find(pre[x]); return x ; } void mix(int x , int y) { int dx = find(x); int dy = find(y); if(dx!=dy) { pre[dx]=dy; vis[dy]+=vis[dx]; } } int main() { while(cin>>m) { if(m==0) { printf("1\n"); continue ; } int a, b ,max ; for (int i = 1 ; i<=10000000+50;i++) { pre[i]=i; vis[i]=1; } max = 0 ; for(int i =1;i<=m;i++) { cin>>a>>b; mix(a,b); } for(int i = 1 ; i<=10000000+50;i++) { if(vis[i]>max) max= vis[i]; } cout<<max<<endl; } return 0 ; }
#include <bits/stdc++.h> using namespace std ; int vis[10000000],pre[10000000],ans , m , n ; int find(int x ) { if(x!=pre[x]) return pre[x]=find(pre[x]); return x ; } void mix(int x , int y) { int dx = find(x); int dy = find(y); if(dx!=dy) { pre[dx]=dy; vis[dy]+=vis[dx]; } } int main() { while(cin>>m) { if(m==0) { printf("1\n"); continue ; } int a, b ,max ; for (int i = 1 ; i<=10000000;i++) { pre[i]=i; vis[i]=1; } max = 0 ; for(int i=1;i<=m;i++) { cin>>a>>b; if(a>max) max=a; if(b>max) max=b; mix(a,b); /*合并集合*/ } int ans=0; for(int i=1;i<=max;i++) if(vis[i]>ans) /*查找最大值*/ ans=vis[i]; cout<<ans<<endl; } return 0 ; }