動物王國中有三類動物A,B,C,這三類動物的食物鍊構成了有趣的環形。A吃B, B吃C,C吃A。
現有N個動物,以1-N編号。每個動物都是A,B,C中的一種,但是我們并不知道它到底是哪一種。
有人用兩種說法對這N個動物所構成的食物鍊關系進行描述:
第一種說法是"1 X Y",表示X和Y是同類。
第二種說法是"2 X Y",表示X吃Y。
此人對N個動物,用上述兩種說法,一句接一句地說出K句話,這K句話有的是真的,有的是假的。當一句話滿足下列三條之一時,這句話就是假話,否則就是真話。
1) 目前的話與前面的某些真的話沖突,就是假話;
2) 目前的話中X或Y比N大,就是假話;
3) 目前的話表示X吃X,就是假話。
你的任務是根據給定的N(1 <= N <= 50,000)和K句話(0 <= K <= 100,000),輸出假話的總數。
Input
第一行是兩個整數N和K,以一個空格分隔。
以下K行每行是三個正整數 D,X,Y,兩數之間用一個空格隔開,其中D表示說法的種類。
若D=1,則表示X和Y是同類。
若D=2,則表示X吃Y。
Output
隻有一個整數,表示假話的數目。
Sample Input
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
Sample Output
3
AC代碼:
include
include
using namespace std;
const int maxn=50000+50;
int a[3*maxn+1],s,N;
int find(int b){
if(a[b]==b) return b;
else return a[b]=find(a[b]);
}
/int find(int b){
while(b!=a[b]){
b=a[b];
}
return b;
}/
void unite(int b,int c){
int x=find(b),y=find(c);
a[y]=x;
}
void diff(int b,int c){
int x=find(b),y=find(c),y1=find(c+2N);
if(x==y||x==y1||b==c) s++;
else {
unite(b,c+N);
unite(b+N,c+2N);
unite(b+2N,c);
}
}
void init(){
for(int i=1;i<=3N+10;i++)
a[i]=i;
}
void same(int b,int c){
int x=find(a[b]),x1=find(a[c+2*N]),y1=find(a[c+N]);
if(x==y1||x==x1) s++;
else{
unite(b,c);
unite(b+N,c+N);
unite(b+2N,c+2N);
}
}
int main(){
int K;
cin>>N>>K;
s=0;
init();
while(K--){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
if(b>N||c>N||c<1||b<1) {
s++;
continue;
}
if(a==1) same(b,c);
else diff(b,c);
// printf("%d %d\n",s,K);
}
printf("%d\n",s);
return 0;
}
注釋:a[x]表示x在A中,a[x+N]表示x在B中,a[x+2*N]表示x在C中,将一種情況分成三種情況
轉載于:https://www.cnblogs.com/sunjianzhao/p/11414529.html