CZY总是遇到这样或那样的问题,现在他又遇到了一个,CZY接到一个大的工程,想想这是走上人生巅峰的第一步啊,CZY想想就高兴,可是这个工程太大了,他需要很多人的帮助才可以,但是为了方便工作,CZY希望他的团队两人两人之间都是朋友关系,或者间接是朋友关系。毕竟是大油水的工程啊,来了一群小伙伴报名,CYZ想请聪明的你帮忙算一算,他可以招到的最大的人数是多少
CZY总是遇到这样或那样的问题,现在他又遇到了一个,CZY接到一个大的工程,想想这是走上人生巅峰的第一步啊,CZY想想就高兴,可是这个工程太大了,他需要很多人的帮助才可以,但是为了方便工作,CZY希望他的团队两人两人之间都是朋友关系,或者间接是朋友关系。毕竟是大油水的工程啊,来了一群小伙伴报名,CYZ想请聪明的你帮忙算一算,他可以招到的最大的人数是多少
输入包含多组测试数据,每组测试数据第一行一个n,表示来报名的小伙伴们的编号1-100,后边接n行,每行两个整数a b,表示编号a和b的小伙伴是朋友关系
输出包括一行,即CZY可以招到的最大的人数是多少
#include<stdio.h> int per[1000]; int num[1000]; int find(int x) { if(per[x]==x) return x; return per[x]=find(per[x]); } void join(int x,int y) { int dx=find(x); int dy=find(y); if(dx!=dy) { per[dy]=dx; //如果根节点不同,并到一起注意dy的根节点为dx ; num[dx]+=num[dy];//就是以dx为根节点的树有多少节点 } } int main() { int T,i,a,b; while(~scanf("%d",&T)) { for(i=1;i<1000;i++) { per[i]=i;//把每个元素的根节点都为它本身 num[i]=1;//数组初始化为1 } for(i=0;i<T;i++) { scanf("%d %d",&a,&b); join(a,b); } int m=0; for(i=0;i<1000;i++)//sum[i]指的是以i为根节点时这棵树的节点 ,求出节点最大值 if(num[i]>m) m=num[i]; printf("%d\n",m); } return 0; }
4 1 2 3 4 5 6 1 6 4 1 2 3 4 5 6 7 8
4 2HintA 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.
这道题目的目的是想知道经过一系列的合并操作之后,查询在所有的子树中,秩的最大值是多少,简而言之,就是最大的那颗子树包含了多少个节点。
很显然,这个问题也能够同时使用两种优化策略,只不过因为要求最大秩的值,需要有一个变量来记录。那么在哪个地方来更新它是最好的呢?我们知道,在按秩进行合并的时候,需要比较两颗待合并子树的秩,因此可以顺带的将对秩的最大值的更新也放在这里进行,实现代码如下:
*我的思路大概是,先建立一个并查集数组,一个标记数组(主要为了防止超时),一个组员数量数组。首先先把并查集数组初始话为本身,并把组员数量初始化为1,之后就是按代码上理解下思路*/
#include<stdio.h> int per[1000000]; int num[1000000]; int find(int x) { if(per[x]==x) return x; return per[x]=find(per[x]); } void join(int x,int y) { int dx=find(x); int dy=find(y); if(dx!=dy) { per[dy]=dx; num[dx]+=num[dy]; } } int main() { int n,i,a,b; while(~scanf("%d",&n)) { if(n==0) { printf("1\n");//在讨论区看到的,不知道为什么? continue; } for(i=1;i<=1000000;i++) { per[i]=i; num[i]=1; } int max=0; for(i=0;i<n;i++) { scanf("%d %d",&a,&b);//求得输入的数字最大是多少,因为爆过一次,所以加上这个 if(a>max) max=a; if(b>max) max=b; join(a,b); } int m=0; for(i=1;i<=max;i++)//直接从1求到max出即可,求出真正最大值 { if(num[i]>m) m=num[i]; } printf("%d\n",m); } return 0; }