這種用並查集判段是否有同性戀的還是第一次做,並查集的功能也太強大了吧。。囧。。
還是說說思路吧;
就是把這些關係分成兩個集合中,同性和異性的,給出的一對數中只要在同一個集合,則他們一定是同性戀;
那麼該怎樣分成兩個集合呢?
下面咱就詳細說說過程吧;
這裏要用到一個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;
}