种类并查集,基本思想是每次压缩路径都必须同时更新子节点和根节点的关系,这种关系是通过子节点和父亲节点的关系,以及父亲节点与根节点的关系运算出来。
压缩路径的findme();参考了大神的代码,做的第二个种类并查集....
#include<stdio.h> #include<string.h> int cri[100005];//记录每一个元素的根节点 int pp[100005];//记录元素与根节点的关系,0代表盟友,1代表敌人 int findme(int a) { if(a==cri[a]) { return a; } int temp=cri[a];//temp用于记录递归前该节点的父亲节点 cri[a]=findme(cri[a]);//找到a节点的根节点 pp[a]=(pp[temp]+pp[a])&1;//通过a节点的父亲节点与根节点的关系以及a节点和其父亲节点的关系更新得到a节点和新的根节点的关系 return cri[a]; } void link(int a, int b) { int ttmp,tmpa,tmpb; tmpa=findme(a); tmpb=findme(b); if(tmpa!=tmpb) { cri[tmpb]=tmpa; pp[tmpb]=(pp[a]+pp[b]+1)&1; } } int main() { int t,n,m,a,b; char ca; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); memset(pp,0,sizeof(pp)); for(int i=1;i<=n;i++) { cri[i]=i; } getchar(); for(int i=0;i<m;i++) { ca=getchar(); if(ca==‘D‘) { scanf("%d%d",&a,&b); getchar(); if(a==b) continue; link(a,b); } else { scanf("%d%d",&a,&b); getchar(); if(findme(a)==findme(b)) { if((pp[a]+pp[b])&1) { printf("In different gangs.\n"); } else { printf("In the same gang.\n"); } } else { printf("Not sure yet.\n"); } } } } return 0; }
原文:http://www.cnblogs.com/tun117/p/4416199.html