pku 1703(种类并查集)
题目链接:http://poj.org/problem?id=1703
思路;个人觉得本质上还是和带权并查集一样的,只不过多了一个MOD操作,然后就是向量关系图稍微改动一下就变成种类并查集了,对于本题,我们可以用一个kind数组来表示是否属于同一类,其中kind[x]==0表示不是同一类,kind[x]==1表示属于同一类,这样我们就可以得到向量关系式了(若r1=Find(u),r2=Find(v),并且parent[r1]=r2,那么就有kind[v]+1==kind[u]+kind[r1])然后变形后对2取余就可以了,即kind[r1]=(kind[v]-kind[u]+1)%2,这是Union部分,还有路径压缩的时候注意更新一下kind[]就ok了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define MAXN 100010 6 int parent[MAXN]; 7 int kind[MAXN]; 8 //0表示不属于同一类,1表示属于同一类 9 int n,m; 10 11 void Initiate() 12 { 13 for(int i=1;i<=n;i++){ 14 parent[i]=i; 15 } 16 memset(kind,0,(n+2)*sizeof(kind[0])); 17 } 18 19 int Find(int x) 20 { 21 if(x==parent[x]){ 22 return parent[x]; 23 } 24 int tmp=Find(parent[x]); 25 kind[x]=(kind[x]+kind[parent[x]])%2; 26 return parent[x]=tmp; 27 } 28 29 void Union(int u,int v) 30 { 31 int r1=Find(u),r2=Find(v); 32 if(r1==r2)return ; 33 parent[r1]=r2; 34 kind[r1]=(kind[v]-kind[u]+1)%2; 35 } 36 37 int main() 38 { 39 // freopen("1.txt","r",stdin); 40 int _case,a,b; 41 char str[4]; 42 scanf("%d",&_case); 43 while(_case--){ 44 scanf("%d%d",&n,&m); 45 Initiate(); 46 while(m--){ 47 scanf("%s%d%d",str,&a,&b); 48 if(str[0]=='D'){ 49 Union(a,b); 50 }else { 51 int r1=Find(a),r2=Find(b); 52 if(r1!=r2){ 53 puts("Not sure yet."); 54 }else if(kind[a]==kind[b]){ 55 puts("In the same gang."); 56 }else { 57 puts("In different gangs."); 58 } 59 } 60 } 61 } 62 return 0; 63 }