POj2492:http://poj.org/problem?id=2492
题意:给你n个虫子,有个人给你m对匹配关系,问你是否出现一对都是同性的情况。
思想:带权并查集数组出现每个的性别,即非0即1,如果都在一个块里面,判断他们的号是否相同,相同就不行,如果不在一个块里,那么就连接2个块,那么就更改某一个的原来的头的性别,然后下次用的时候更新下即可。
至于为何这样去更改原来父亲节点的权值,可以自己去算一下4种可能,发现就是这样。
#include<stdio.h>
int fa[2005];
int sum[2005];
int find(int x)
{
if(x==fa[x])
return x;
int fx=fa[x];
fa[x]=find(fa[x]);
sum[x]=(sum[x]+sum[fx])%2;//连接之后更新关系 从后往前
return fa[x];
}
int main()
{
int t;
scanf("%d",&t);
for(int Case=1;Case<=t;Case++)
{
int n,m,flag;
flag=1;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)
{
fa[i]=i;
sum[i]=0;
}
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(flag==0)//已经错了
continue;
int fx=find(u);
int fy=find(v);
if(fx==fy)//在一个链里面
{
if((sum[u]+sum[v])%2==0)//说明在一起的而且是一个种类
flag=0;
}
else//2个链
{
fa[fx]=fy;
sum[fx]=(sum[u]+sum[v]+1)%2;
}
}
printf("Scenario #%d:\n",Case);
if(flag)
printf("No suspicious bugs found!\n");
else
printf("Suspicious bugs found!\n");
printf("\n");
}
return 0;
}
codeforces:http://codeforces.com/gym/100923/problem/H
题意:已知有n个战士,分属于两个红、蓝阵营,现输入m条敌对关系,当本条关系信息与之前的真的关系信息冲突,则认为本条关系信息为假(即先输入的敌对关系优先为真)。
#include<stdio.h>
int fa[200005];
int sum[100005];
int find(int x)
{
if(x==fa[x])
return x;
int fx=fa[x];
fa[x]=find(fa[x]);
sum[x]=(sum[x]+sum[fx])%2;//连接之后更新关系 从后往前
return fa[x];
}
int main()
{
int t;
freopen("meciul.in", "r", stdin);
freopen("meciul.out", "w", stdout);
scanf("%d",&t);
for(int Case=1;Case<=t;Case++)
{
int n,m,flag;
flag=1;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)
{
fa[i]=i;
sum[i]=0;
}
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
int fx=find(u);
int fy=find(v);
if(fx==fy)//在一个链里面
{
if((sum[u]+sum[v])%2==0)//说明在一起的而且是一个种类
printf("NO\n");
else
printf("YES\n");
}
else//2个链
{
printf("YES\n");
fa[fx]=fy;
sum[fx]=(sum[u]+sum[v]+1)%2;
}
}
}
return 0;
}