POJ 1611非典传染[并查集]

10 篇文章 0 订阅
1 篇文章 0 订阅

题目连接

http://acm.hust.edu.cn/vjudge/problem/10536

Sample Input

100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
200 2
1 5
5 1 2 3 4 5
1 0
0 0

Sample Output

4
1
1

题意

0号学生是,非典传染源,与他同组的学生都有感染非典的嫌疑,找出所有有嫌疑的学生。

题解

标准的并查集,可以把rank[0]设置得特别大,然后所有与他有关联的学生都向他连根,还有就是原则上每组的其他人都与第一个人进行Union。

代码

#include<iostream>
  #include<cstdio>
  #include<cstring>
  #include<string>
  #include<cmath>
  #include<string>
 #include<cctype>
  #include<algorithm>
  #include<vector>
  int father[30005];
  int rank[30005];
  int start(int n)
  {
      for(int i=0;i<n;i++)
      {
          father[i]=i;
          rank[i]=0;
      }
  }
  int find(int x)
  {
      if(x!=father[x])
      {
          father[x]=find(father[x]);
      }
      return father[x];
  }

  void unin(int x,int y)
  {
      int fatherx=find(x);
      int fathery=find(y);
      if(fatherx==fathery)return ;
      if(rank[fatherx]<rank[fathery])
      {
          father[fatherx]=fathery;
          //rank[y]++;
      }
      else
      {
          father[fathery]=fatherx;
         if(rank[fatherx]==rank[fathery]) rank[fatherx]++;
      }
  }


  int main()
  {
     int p,q;
     while(scanf("%d%d",&p,&q)!=EOF)
     {
         if(p==0&&q==0)break;
         start(p);
         rank[0]=1e9;
         for(int i=0;i<q;i++)
         {
             int t;
             scanf("%d",&t);
             int k,kk;
                 int kkk;
                 scanf("%d",&kkk);
             for(int j=0;j<t-1;j++)
             {


                 scanf("%d",&kk);

                 if(find(kkk)!=find(kk))unin(kkk,kk);
             }
         }
         if(q==0){printf("1\n");continue;}
         int cnt=1;
         for(int i=1;i<=p-1;i++)if(find(i)==0)cnt++;
         printf("%d\n",cnt);
     }
      return 0;
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值