对于每只动物i创建3个元素i-A,i-B,i-C,用3 x N个元素建立并查集
第一种,x和y属于同一种类, 合并x-A和y-A,x-B和y-B,x-C和y-C;
第二种,x吃y,合并x-A和y-B,x-B和y-C,x-C和y-A
合并过程中判断是否矛盾,x-A和y-B或y-C是否在同一组。
#include <stdio.h>
#include <string.h>
#define max_N 150001
int par[max_N];
int rank[max_N];
void init(int n)//初始化par
{
for(int i=0;i<n;i++)
{
par[i]=i;
rank[i]=0;
}
}
int find(int x)//查找x的根节点
{
while(x!=par[x])
x=par[x];
return x;
}
void unite(int x,int y)
{
x=find(x);//x的根节点
y=find(y);//y的根节点
if(x==y)
return;
if(rank[x]<rank[y]) // 合并
{
par[x] =y;
}
else
{
par[y]=x;
if(rank[x]==rank[y])
{
rank[x]++;
}
}
}
bool same(int x,int y)
{
return find(x)==find(y);
}
int main()
{
int n,M;
scanf("%d%d",&n,&M);
int ans=0;
init(n*3);
int t,x,y;
for(int i=0;i<M;i++)
{
scanf("%d%d%d",&t,&x,&y);
--x;
--y;
if(x>=n||y>=n||(x==y&&t==2)||x<0||y<0)
{
ans++;
continue;
}
if (t==1)//“x 和 y 属于同一类”的信息
{
if (same(x,y+n)||same(x,y+2*n))
{
ans++;
}
else
{
unite(x,y);
unite(x+n,y+n);
unite(x+n*2,y+n*2);
}
}
else// "x吃y的信息"
{
if(same(x,y)||same(x,y+2*n))
{
ans++;
}
else
{
unite(x,y+n);
unite(x+n,y+2*n);
unite(x+2*n,y);
}
}
}
printf("%d\n",ans);
return 0;
}
并查集算法解析
410

被折叠的 条评论
为什么被折叠?



