给出K句话来描述N个动物(各属于A、B、C三类之一)之间的关系,格式及意义如
下:
1X Y:表示X与Y是同类;
2X Y:表示X吃Y。
K句话中有真话有假话,当一句话满足下列三条之一时,这句话就是假话,否则就是
真话。
1)当前的话与前面的某些真的话冲突,就是假话;
2)当前的话中X或Y比N大,就是假话;
3)当前的话表示X吃X,就是假话。
1)当前的话与前面的某些真的话冲突,就是假话;
2)当前的话中X或Y比N大,就是假话;
3)当前的话表示X吃X,就是假话。
求假话的总数。
做法:由于对每个动物的种类未知,我们用3个堆来表示一个动物,即一个动物可以由
三种形态,A,B,C;如果两个动物为同类,我们就把这两个动物的3个堆合并。如果
x吃y,我们就将x-a,y-b;x-b,y-c;x-c,y-a合并。其中1个动物的堆用x,x+n,x+2n
表示。
代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int MAX=50000;
int par[3*MAX+50];
int Find(int a)
{
if(par[a]!=a)
par[a]=Find(par[a]);
return par[a];
}
bool same(int x,int y)
{
return Find(x)==Find(y);
}
void merge(int a,int b)
{
int p1=Find(a);
int p2=Find(b);
if(p1==p2)
return ;
par[p2]=p1;
}
int main()
{
int n,m,ans=0;
int a,b,c,i;
scanf("%d%d",&n,&m);
for(i=0;i<=3*n;i++)
par[i]=i;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
b=b-1;c=c-1;
if(b>=n||c>=n||b<0||c<0){ans++;continue;}
if(a==1)
{
if(same(b,c+n)||same(b,c+2*n))
ans++;
else
merge(b,c),merge(b+n,c+n),merge(b+2*n,c+2*n);
}
else if(a==2)
{
if(same(b,c)||same(c,b+n))
ans++;
else
merge(b,c+n),merge(b+n,c+2*n),merge(b+2*n,c);
}
}
printf("%d\n",ans);
return 0;
}