# POJ1182：食物链(并查集)

 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 94930 Accepted: 28666

Description:

1） 当前的话与前面的某些真的话冲突，就是假话；
2） 当前的话中X或Y比N大，就是假话；
3） 当前的话表示X吃X，就是假话。

Input:

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

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

const int N = 150005;
int f[N];
int n,k,ans;

int find(int x){return f[x]==x ? x : f[x]=find(f[x]);}

bool same(int x,int y){
return find(x)==find(y);
}

void Union(int x,int y){
int fx=find(x),fy=find(y);
f[fx]=fy;
}

int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=3*n+1;i++) f[i]=i;
while(k--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(x<1 || y<1 ||x>n ||y>n){
ans++;continue ;
}
int fx=find(x),fy=find(y);
if(op==1){
if(same(x,y+n) ||same(x,y+2*n)){
ans++;continue;
}
Union(x,y);Union(x+n,y+n);Union(x+2*n,y+2*n);
}else{
if(same(x,y) || same(x,y+2*n)){
ans++;continue ;
}
Union(x,y+n);Union(x+n,y+2*n);Union(x+2*n,y);
}
}
printf("%d",ans);
return 0;
}
View Code

//带权并查集
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

const int N = 5e4+5;
int f[N],r[N]={0};
int n,k,ans=0;

int find(int x){
if(f[x]==x) return x;
int tmp = f[x];
f[x]=find(f[x]);
r[x]=(r[x]+r[tmp])%3;
return f[x];
}

int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n+1;i++) f[i]=i;
while(k--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(x<1 || y>n ||x>n ||y<1){ans++;continue ;}
int fx=find(x),fy=find(y);
if(fx==fy){
if((r[x]-r[y]+3)%3!=op-1) ans++;
}else{
f[fy]=fx;
if(op==1) r[fy]=(r[x]+(3-r[y]))%3;
else r[fy]=(r[x]+(3-r[y])+op);
}
}
printf("%d",ans);
return 0;
}
View Code

posted @ 2018-11-18 23:07  heyuhhh  阅读(284)  评论(0编辑  收藏  举报