并查集
如下图所示
所以我们就可以想一个办法,如何找到自家的老大。
先令每个人的老大就是自己,然后当遇到另一个和自己有关系的人的时候,便去问候一下对方的老大,比如今天某席大侠和某陈大仙女走进同一家面馆吃面,信竞中人,一言不合就要开始【哔~】,但当他们要开始【哔】之前,自然要问候一下对方的老大。我们可以用一个pre数组来存每一个人的老大
然后他们就委托自己的上级去找老大。
int find(int x)
{
int r=x;
while(pre[r]!=r) //席大侠和陈大仙女找到自己的上一级宋师兄等人
r=pre[r]; //一层层往上找
return r; //找出幕后老大何X
}
最终发现竟然是一个老大(还好没打起来!!!)
但如果不是一个老大,如当年武林大比之时,何X与黄(fang)勇各领风骚,都想称霸德瑞黑心集团,他们谁也不服谁,但一山不容二虎,这时就只好有一人得屈居人下。
void join(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx!=fy)
pre[fx]=fy;//屈居人下
}
这时就又有一个问题了,信竞中人,讲究雷厉风行,一个一个找上级太麻烦了,还不如直接找到老大
所以就变成了下面这样:
int find(int x)
{
int i,j,r;
r=x;
while(r!=pre[r]) //不是老大
{
r=pre[r]; //向上找
}
i=x;
while(i!=r) //把所有人的上级直接改为老大
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
所以但席大侠和陈大侠女再一起吃面时,他们就可以直接说出,老纸(娘)滴老大是何X!!
【完整代码】上面辣么多文字我也没看懂,还是看看代码吧
#include<bits/stdc++.h>
using namespace std;
int n,m,pre[10100];
int find(int x)
{
int i,j,r;
r=x;
while(r!=pre[r])
{
r=pre[r];
}
i=x;
while(i!=r)
{
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
void join(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx!=fy)
{
pre[fx]=fy;
}
}
int main()
{
cin>>n>>m;
int z,x,y;
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=1;i<=m;i++)
{
cin>>z>>x>>y;
if(z==1)
{
join(x,y);
}
if(z==2)
{
int p=find(x),q=find(y);
if(p==q)
{
cout<<'Y'<<endl;
}
else
{
cout<<'N'<<endl;
}
}
}
return 0;
}