hdu 1829 A Bug's Life 并查集(囧)

来源:互联网 发布:跑跑辅助源码猴岛 编辑:程序博客网 时间:2024/06/14 14:40

这种用并查集判段是否有同性恋的还是第一次做,并查集的功能也太强大了吧。。囧。。

还是说说思路吧;

就是把这些关系分成两个集合中,同性和异性的,给出的一对数中只要在同一个集合,则他们一定是同性恋;

那么该怎样分成两个集合呢?

下面咱就详细说说过程吧;

这里要用到一个next数组,它记录的是恋人之间的关系:

next【i】=j,就表示i的恋人是j了;

如果next【i】==0,则此时的恋人关系可以确定next【i】=j。

如果next【i】不等于零,则next记录的一定是他的上一个恋人,则next【i】和j是同性关系了,则此时便可以next【i】和j合并到一个数组中了。。

判段next时,一定要注意对i,j都判断。即如果next【i】==0;时next【i】=j,同时判段next【j】与0的关系来确定是否进行合并。。

 

到此这题就可以结束了。。

至此我们知道了并查集不仅可以判段,所给出点的关系中会有几个集合,每个集合有几种元素。

他还可以确定是否会出现同性恋的问题;

啰嗦了这么多就是想更好地掌握并查集的用法来解决更多的实际问题。。

 

#include"stdio.h"
#include"string.h"
int pre[3000],next[3000000];
int find(int k)
{
 if(k!=pre[k])
  pre[k]=find(pre[k]);
 return pre[k];
}
void Union(int x,int y)
{
 x=find(x);
 y=find(y);
 if(x!=y)
  pre[y]=x;
}
int main()
{
 int m,n,i,j=1,k,p,t;
 scanf("%d",&k);
 while(k--)
 {
  scanf("%d%d",&m,&n);
  for(i=1;i<=m;i++)
   pre[i]=i;
  memset(next,0,sizeof(next));
  int flag=0;
  for(i=0;i<n;i++)
  {
   scanf("%d%d",&p,&t);
   if(find(p)==find(t))
    flag=1;
   else
   {
    if(next[p]==0)
     next[p]=t;
    else
    {
     Union(next[p],t);
    }
    if(next[t]==0)
     next[t]=p;
    else
    {
     Union(next[t],p);
    }
   }
  }
  printf("Scenario #%d:\n",j++);
  if(flag)
   printf("Suspicious bugs found!\n\n");
  else
   printf("No suspicious bugs found!\n\n");
 }
 return 0;
}


 

原创粉丝点击