http://poj.org/problem?id=1182
带权并查集第一题,三种类型的生物,分别加入三个集合,题解见注释
#include <iostream> #include <cstdio> #include <cstring> using namespace std ; #define MAX_N 150005 int par[MAX_N] ;//父亲 int rank[MAX_N] ;//树的高度 void INIT(int n) { for(int i=0 ;i<n ;i++){ par[i]=i ; rank[i]=0 ; } } int find(int x) { if(par[x]==x){ return x ; } else{ return par[x]=find(par[x]) ; } } void unite(int x,int y) { x=find(x) ; y=find(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 n,k,T[100005],X[100005],Y[100005] ; void solve() { //x x+n x+2*n 分别代表A B C类 //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 //提前判断矛盾 INIT(3*n) ; int ans=0 ; for(int i=0 ;i<k ;i++) { int t=T[i] ; int x=X[i]-1,y=Y[i]-1 ; if(x<0 || x>=n || y<0 || y>=n) { ans++ ; continue ; } if(t==1) { if(same(x,y+n) || same(x,y+2*n)) { ans++ ; } else { unite(x,y) ; unite(x+n,y+n) ; unite(x+2*n,y+2*n) ; } } else { 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) ; } int main() { scanf("%d%d",&n,&k) ; for(int i=0 ;i<k ;i++) scanf("%d%d%d",&T[i],&X[i],&Y[i]) ; solve() ; return 0 ; }
常规带权并查集解法
#include <iostream> #include <cstdio> #include <set> #include <cmath> using namespace std ; #define MAX_N 50005 int par[MAX_N] ;//父亲 int rank[MAX_N] ;//树的高度 void INIT(int n) { for(int i=0 ;i<n ;i++){ par[i]=i ; rank[i]=0 ; } } int find(int x) { if(par[x]==x){ return x ; } else{ int temp=par[x] ; par[x]=find(par[x]) ; rank[x]=(rank[x]+rank[temp])%3 ; return par[x] ; } } void unite(int x,int y,int d) { int xp=find(x) ; int yp=find(y) ; par[xp]=yp ; rank[xp]=(rank[y]-rank[x]+3+d)%3 ; } bool same(int x,int y) { return find(x)==find(y) ; } int n,k,T[100005],X[100005],Y[100005] ; void solve() { INIT(n) ; int ans=0 ; for(int i=0 ;i<k ;i++) { int t=T[i] ; int x=X[i]-1,y=Y[i]-1 ; if(x<0 || x>=n || y<0 || y>=n) { ans++ ; continue ; } int xp=find(x) ; int yp=find(y) ; if(xp==yp) { if((rank[x]-rank[y]+3)%3!=t-1) ans++ ; } else { unite(x,y,t-1) ; } } printf("%d\n",ans) ; } int main() { scanf("%d%d",&n,&k) ; for(int i=0 ;i<k ;i++) scanf("%d%d%d",&T[i],&X[i],&Y[i]) ; solve() ; return 0 ; }