标签:操作 lse red min cat code root 两种 font
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 52925 | Accepted: 16209 |
Description
Input
Output
Sample Input
1 5 5 A 1 2 D 1 2 A 1 2 D 2 4 A 1 4
Sample Output
Not sure yet. In different gangs. In the same gang.
Source
union_set(x, y)同属于第一个团伙
union_set(x+n,y+n)同属于第二个团伙
union_set(x+n, y)表示x属于第二个团伙,y属于第一个团伙
union_set(x, y+n)表示x属于第一个团伙,y属于第二个团伙;
每次告诉你x和y属于不同团伙,有两种情况,x属于1,y属于2
x属于2,y属于1,所以需要这样进行两次合并
确定是否属于相同团伙的话
x与y的根结点相同或者x+n与y+n的根结点相同 都属于相同犯罪团伙
x+n与y根结点相同或者x与y+n的根结点相同,都属于不同犯罪团伙
其他情况就不能确定了
这个思路很巧妙,也比较简单,不用具体确定x属于1还是2
code:
#include<queue> #include<set> #include<cstdio> #include <iostream> #include<algorithm> #include<cstring> #include<cmath> using namespace std; #define max_v 100005 int pa[max_v*2]; int rk[max_v*2]; int n,m; void init() { for(int i=0; i<=2*n; i++) { pa[i]=i; rk[i]=0; } } int find_set(int x) { if(x!=pa[x]) pa[x]=find_set(pa[x]); return pa[x]; } void union_set(int x,int y) { x=find_set(x); y=find_set(y); if(x==y) return ; if(rk[x]>rk[y]) pa[y]=x; else { pa[x]=y; if(rk[x]==rk[y]) rk[y]++; } } int f(int x,int y) { return find_set(x)==find_set(y); } int main() { int t; scanf("%d",&t); int x,y; char str[10]; while(t--) { scanf("%d %d",&n,&m); init(); for(int i=0; i<m; i++) { scanf("%s %d %d",str,&x,&y); if(str[0]==‘D‘) { union_set(x+n,y); union_set(x,y+n); } else if(str[0]==‘A‘) { if(f(x,y)||f(x+n,y+n)) printf("In the same gang.\n"); else if(f(x+n,y)||f(x,y+n)) printf("In different gangs.\n"); else printf("Not sure yet.\n"); } } } return 0; }
POJ 1703 Find them, Catch them(确定元素归属集合的并查集)
标签:操作 lse red min cat code root 两种 font
原文地址:https://www.cnblogs.com/yinbiao/p/9463647.html