哎哎。。刚刚开始学习并査集不久,就遇到这样一个问题,相当头疼,于是就搜解题报告,后面发现有一个人的思路给人很明了的赶脚....于是...盗版了过来..
第一个代码是把rank存放敌友关系,我有点没理解find过程中的rank的转变,如果有知道的可以指点在下,
第二个代码就是加一个数组存放敌人,在这个过程中,根据 D a b 我们就把a,b互相存为敌人,合并过程中就合并对方的敌人,也就是敌人的敌人是自己的朋友,然后就转变成了并査集的基础,合并相同的集合....
/*#include <iostream> #include <cstdio> using namespace std; int rank[100010]; int parent[100010]; void make_set(int n){ for(int i=0;i<n;i++){ parent[i]=i; rank[i]=0;//0代表和父节点同类,1代表异类 } } int find_set(int x){ int t=parent[x]; if(x!=parent[x]){ parent[x]=find_set(t); rank[x]=(rank[t]+rank[x])%2;//回溯跟新 和父节点相同为0,不同为1 } return parent[x]; } void union_set(int x,int y){ int fx=find_set(x); int fy=find_set(y); if(fx==fy) return; parent[fx]=fy; rank[fx]=(rank[x]+rank[y]+1)%2;//根据x与其根,y与其根,x与y的关系,推导出fx与fy的关系 } int main(){ int nCase; scanf("%d",&nCase); while(nCase-->0){ int n,m,a,b; char c; scanf("%d%d",&n,&m); make_set(n); while(m-->0){ getchar(); scanf("%c%d%d",&c,&a,&b); if(c=='D'){ union_set(a,b); }else{ int x=find_set(a); int y=find_set(b); if(x==y){ if(rank[a]==rank[b]){ printf("In the same gang.\n"); }else printf("In different gangs.\n"); }else{ printf("Not sure yet.\n"); } } } } return 0; }*/ #include<stdio.h> int father[100005];//看看有没有必要加秩,按其合并,加了快le几十ms int enemy[100005];//存放敌人 int rank[100005]; void init(int n) { for(int i=1;i<=n;i++)//注意从1开始 { father[i]=i; enemy[i]=0; rank[i]=0; } } int find(int x) { if(x!=father[x]) father[x]=find(father[x]); return father[x]; } void Union(int x,int y) { int fx=find(x); int fy=find(y); if(fx == fy) return ; if(rank[fx]>rank[fy]) { father[fy]=fx; } else { father[fx]=fy; if(rank[fx] == rank[fy]) rank[fy]++; } //father[fx]=fy; } int main() { int T; int n,m; int a,b; char c; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); init(n); getchar(); while(m--) { scanf("%c%d%d",&c,&a,&b); getchar(); if(c == 'D') { if(enemy[a]==0 && enemy[b] == 0)//开始a,b都没有敌人不用合并,存放对方为敌人 { enemy[a]=b;enemy[b]=a; } else if(enemy[a] == 0)//a没有存放敌人,现在存放敌人b,而b有敌人,那么敌人的敌人是朋友,就合并 { enemy[a]=b; Union(a,enemy[b]); } else if(enemy[b] == 0)//同理 { enemy[b]=a; Union(b,enemy[a]); } else//都存在敌人,就都合并一次 { Union(a,enemy[b]); Union(b,enemy[a]); } } else { if(find(a) == find(b))//首先a,b在一个集合 printf("In the same gang.\n"); else if(find(a)==find(enemy[b])||find(b)==find(enemy[a]))/ printf("In different gangs.\n"); else printf("Not sure yet.\n"); } } } return 0; }