hdu1856 选出更多的孩子

题目大意:

老师选取2个学生对应的号码,这两人视作朋友,同时朋友的朋友也可以看成自己的朋友。

最后老师选出一个人数最多的朋友圈。

这里学生的人数不大于10^7,所以操作时需要极为注意,操作步数能省则省。

我也在超时了两次之后,不断进行代码优化才做出。

 

超时的部分函数代码:

1 int getHead(int x)

2 {

3     while(x!=fa[x]) x=fa[x];

4     return x;

5 }

后来在这个代码基础上加了int a=x;return前加一个fa[a]=x;这样在查找顶点时,同时将路径进行压缩,下次再去查找时就不会有重复的操作。

 

之前的联合函数
void Union(int x,int y)
{

    int
fa_x=getHead(x);
    int
fa_y=getHead(y);
    if
(fa_x!=fa_y) {fa[fa_x]=fa_y;K[fa_y]+=K[fa_x];}
}

这是将每个作为顶点位置上对应的小组人数保存在K数组中,但是这样在main函数中要对K数组进行一次遍历(10^7次的操作,又浪费时间了)
所以后来引进了Max的全局变量,每次结合时就更新Max,那么main函数中直接输出Max即可.

改过之后函数变为:

void Union(int x,int y)
{

    int
fa_x=getHead(x);
    int
fa_y=getHead(y);
    if
(fa_x!=fa_y) {fa[fa_x]=fa_y,fa[x]=fa_y;K[fa_y]+=K[fa_x];}
    Max=max(Max,K[fa_y]);
}

总体代码如下:

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 using namespace std;

 5 #define MAXN 10000100

 6 int Max;

 7 int fa[MAXN],K[MAXN];

 8 

 9 int max(int x,int y)

10 {

11     return x>y?x:y;

12 }

13 int getHead(int x)

14 {

15     int a=x;

16     while(x!=fa[x]) x=fa[x];

17     fa[a]=x;

18     return x;

19 }

20 void Union(int x,int y)

21 {

22     int fa_x=getHead(x);

23     int fa_y=getHead(y);

24     if(fa_x!=fa_y) {fa[fa_x]=fa_y,fa[x]=fa_y;K[fa_y]+=K[fa_x];}

25     Max=max(Max,K[fa_y]);

26 }

27 int main()

28 {

29     int n,t;

30     while(scanf("%d",&n)!=EOF){

31         t=0;

32         int *a=new int[n];

33         int *b=new int[n];

34         for(int i=1;i<=MAXN;i++){

35             K[i]=1;

36             fa[i]=i;

37         }

38         Max=1;

39         for(int i=0;i<n;i++){

40             scanf("%d%d",&a[i],&b[i]);

41             Union(a[i],b[i]);

42         }

43 

44         printf("%d\n",Max);

45     }

46     return 0;

47 }

你可能感兴趣的:(HDU)