我们理解并查集这个数据结构的时候不要过于死板,我们要知道
并查集是用来维护关系的,而不是单纯一味去归并,归并,归并
下面给出一个问题尝试用并查集来解决:一共有两个类,然后告诉你若干组数据,每一组数据的两个元素不是一类的,然后在线判断两个元素是否是同一类
这个时候如果你只会归并就行不通的,还需要一些特殊的处理
我们需要在并查集的那个数组的基础之上,需要另一个数组来记录这种特殊的现象
int set[maxn],a[maxn]; //a表示这个节点和父节点的关系,0表示相同1表示不同
接下来我们的路径压缩加找祖宗函数也需要相应的调整,要不断更新a的值才行
int find(int x) { if (x==set[x]) return x; //x的父节点是祖先节点的情况,不需要改变a的值 int t=find(set[x]); a[x]=(a[set[x]]+a[x])%2; //判断归并之后x和祖先的团伙关系 return set[x]=t; }
归并的时候还是很简单的,但是也要同时去更新a的值
void Union(int x, int y) { int fx=find(x); int fy=find(y); set[fx]=fy; //根据x和y不同确定x和x的祖先节点的同伙关系 if (a[y]==0) a[fx]=1-a[x]; else a[fx]=a[x]; }
我们在判断的时候,已知的情况都已经归并到一棵树里面,并且有a数组记录已知情况下所有元素的关系,直接判断即可
fx=find(x); fy=find(y); if (fx!=fy) printf("Not sure yet.\n"); else if(a[x]==a[y]) printf("In the same gang.\n"); else printf("In different gangs.\n");
接下来我们给出完整的实现,这道题的大意是这样的,有两个犯罪团伙,然后告诉你若干个关系,关系是两个犯人不是一个团伙的,然后在线判断给定的两个犯人之间的关系
1 //一共有两类,给定某两个元素之间的不同类关系 2 //判断当前给定情况下某两个元素是否同类 3 #include<iostream> 4 #include <cstdio> 5 #include <cstring> 6 using namespace std; 7 const int maxn=100005; 8 int t,n,m; 9 int fx,fy,x,y; 10 char c; 11 int set[maxn],a[maxn]; 12 //a表示这个节点和父节点的关系,0表示相同1表示不同 13 int find(int x) 14 { 15 if (x==set[x]) return x; 16 //x的父节点是祖先节点的情况,不需要改变a的值 17 int t=find(set[x]); 18 a[x]=(a[set[x]]+a[x])%2; 19 //判断归并之后x和祖先的团伙关系 20 return set[x]=t; 21 } 22 void Union(int x, int y) 23 { 24 int fx=find(x); 25 int fy=find(y); 26 set[fx]=fy; 27 //根据x和y不同确定x和x的祖先节点的同伙关系 28 if (a[y]==0) 29 a[fx]=1-a[x]; 30 else 31 a[fx]=a[x]; 32 } 33 int main() 34 { 35 36 cin>>t; 37 while (t--) 38 { 39 cin>>n>>m; 40 for (int i=1; i<=n; i++) 41 { 42 set[i] = i; 43 a[i] = 0; 44 } 45 while(m--) 46 { 47 cin>>c>>x>>y; 48 if (c==‘A‘) 49 { 50 fx=find(x); 51 fy=find(y); 52 if (fx!=fy) 53 printf("Not sure yet.\n"); 54 else if(a[x]==a[y]) 55 printf("In the same gang.\n"); 56 else 57 printf("In different gangs.\n"); 58 } 59 else 60 Union(x, y); 61 } 62 } 63 return 0; 64 }
原文地址:https://www.cnblogs.com/aininot260/p/9304501.html
时间: 2024-10-10 02:27:56