这是并查集的一种变形。在这种并查集中,节点被分为了不同的n类(类别一般较少)。其大致结构与并查集相同,但区别在于,分组并查集需要一个relation数组,来存储节点的种类。这就需要注意结点与其根节点之间的关系。下面具体问题具体分析。
2 3 3 1 2 2 3 1 3 4 2 1 2 3 4Sample Output
Scenario #1: Suspicious bugs found! Scenario #2: No suspicious bugs found!
如1->2,2->3,3->1,则一定存在同性的昆虫。
代码:
#include
#include
#include
#define N 2005
using namespace std;
int root[N],relation[N], n, k;
int flag;
int T,a,b;
int findroot(int x)
{
if(x==root[x])
return root[x];
int t=findroot(root[x]);
relation[x]=(relation[root[x]]+relation[x])%2; //由根向下更改现结点与新的根节点的关系
root[x]=t;
return root[x];
}
void Union(int x,int y)
{
int a=findroot(x),b=findroot(y);
if(a==b) //根节点相同,判断与根节点的关系是否相同
{
if(relation[x]==relation[y])
flag=1;
return;
}
root[a]=b;
relation[a]=(relation[x]-relation[y]+1+2)%2; //根节点不同,并查集合并,并且更改根节点之间的关系
}
int main()
{
scanf("%d",&T);
for (int Case=1;Case<=T;Case++)
{
scanf("%d%d",&n,&k);
flag=0;
for(int i=0;i<=n;i++)
root[i]=i,relation[i]=0;
for(int i=0;i
100 7 1 101 1 2 1 2 2 2 3 2 3 3 1 1 3 2 3 1 1 5 5Sample Output
3
代码:
//By Sean Chen
#include
#include
#include
#include
using namespace std;
int n,m,root[50005],relation[50005];
int d,a,b;
int cnt;
int findroot(int x)
{
if (x==root[x])
return x;
int t=findroot(root[x]);
relation[x]=(relation[root[x]]+relation[x])%3;
root[x]=t;
return t;
}
void Uni(int x,int y)
{
int ra=findroot(x),rb=findroot(y);
if (ra==rb)
{
if (d==1 && relation[x]!=relation[y])
cnt++;
if (d==2)
{
if (relation[x]==1 && relation[y]!=0)
cnt++;
if (relation[x]==2 && relation[y]!=1)
cnt++;
if (relation[x]==0 && relation[y]!=2)
cnt++;
}
}
else
{
root[ra]=rb;
if (d==1)
relation[ra]=(relation[y]-relation[x]+3)%3;
else
relation[ra]=(relation[y]-relation[x]+3+1)%3;
}
return;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=0;i<=n;i++)
{
relation[i]=0;
root[i]=i;
}
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&d,&a,&b);
if (a>n || b>n || (d==2 && a==b))
{
cnt++;
continue;
}
Uni(a,b);
}
cout<