HDU 5285 wyh2000 and pupil

分析:这题和POJ 2492差不多,所以我用的是并查集,可以把题意理解为有很多人,要分成两个帮派,每个帮派至少有1个人,输入n,m分别代表n个人,和m对有冲突的人,有冲突的不能在一个帮派里,要尽可能的使第一个帮派的人多一些,如果存在输出第1,2个帮派的人数,否则输出Poor wyh 。如果输入n=0或n=1的话肯定不满足题意,用root[]数组记录每个人的老大是谁,opp[]记录每个人的对手是谁,child[]记录每个人手下有几个小弟,visit[]记录每个人有没有被访问过。初始化每个人都没有对手,如果a有对手,b没有,那么opp[b]=a,把b加入到a的对手的集合中,集合的根为老大,a没有对手,b有同理;a,b都有对手,就把a加入到b的对手的集合,b加入到a的对手的集合。最后取每两个对立的小帮派中人数较多的,和不与任何人对立的形成一个大帮派。

# include <stdio.h>
# define max(x,y) x>y?x:y
  int root[100005],opp[100005],visit[100005],child[100005];
  int Find(int x)
  {
      if(x==root[x])
        return x;
      root[x]=Find(root[x]);
      return root[x];
  }
  void Union(int x,int y)
  {
      int fx=Find(x),fy=Find(y);
      root[fx]=fy;
  }
  int main()
  {
      int i,a,b,n,m,t,flag,ans;
      scanf("%d",&t);
      while(t--)
      {
          scanf("%d%d",&n,&m);
          if(n<=1)
          {printf("Poor wyh\n");continue;}
          for(i=1;i<=n;i++)
          {
              root[i]=i;
              opp[i]=visit[i]=child[i]=0;
          }
          flag=ans=0;
          while(m--)
          {
              scanf("%d%d",&a,&b);
              if(flag==1)
                continue;
              if(Find(a)==Find(b))
                flag=1;
              else if(opp[a]==0&&opp[b]==0)
              {
                  opp[a]=b;
                  opp[b]=a;
              }
              else if(opp[a]==0)
              {
                  opp[a]=b;
                  Union(a,opp[b]);
              }
              else if(opp[b]==0)
              {
                  opp[b]=a;
                  Union(b,opp[a]);
              }
              else
              {
                  Union(a,opp[b]);
                  Union(b,opp[a]);
              }
          }
          if(flag==1)
            printf("Poor wyh\n");
          else
          {
              for(i=1;i<=n;i++)
                child[Find(i)]++;
              for(i=1;i<=n;i++)
                if(!visit[Find(i)])
                {
                    visit[Find(i)]=1;
                    if(!opp[Find(i)])
                      ans++;
                    else
                    {
                        visit[Find(opp[Find(i)])]=1;
                        ans+=max(child[Find(i)],child[Find(opp[Find(i)])]);
                    }
                }
                if(ans!=n)
                  printf("%d %d\n",ans,n-ans);
                else
                  printf("%d %d\n",n-1,1);
          }
      }
      return 0;
  }


你可能感兴趣的:(ACM)