Find them, Catch them
直接翻译了
Descriptions
警方决定捣毁两大犯罪团伙:龙帮和蛇帮,显然一个帮派至少有一人。该城有N个罪犯,编号从1至N(N<=100000。将有M(M<=100000)次操作。D a b 表示a、b是不同帮派
A a b 询问a、b关系
Input
多组数据。第一行是数据总数 T (1 <= T <= 20)每组数据第一行是N、M,接下来M行是操作Output
对于每一个A操作,回答"In the same gang."或"In different gangs." 或"Not sure yet."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.
题目链接
https://vjudge.net/problem/POJ-1703
定义并查集为:
并查集里的元素i-x表示i属于帮派x
同一个并查集的元素同时成立
可见所有元素个数为2 * N,如果i表示属于帮派A,那么i + N表示属于帮派B,每次输入两个家伙不在同一帮派的时候,就合并他们分属两个帮派的元素。
注意这题如果用cin的话会TLE
AC代码
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include <sstream> #define IOS ios_base::sync_with_stdio(0); cin.tie(0); #define Mod 1000000007 #define eps 1e-6 #define ll long long #define INF 0x3f3f3f3f #define MEM(x,y) memset(x,y,sizeof(x)) #define Maxn 100000 * 2 + 10 using namespace std; int T,N,M; int par[Maxn];//par[i] i的根 void init(int n) { for(int i=0; i<=n; i++) par[i]=i; } int findr(int x)//查询根 { if(par[x]==x) return x; return par[x]=findr(par[x]); } void unite(int x,int y)//合并 { x=findr(x); y=findr(y); if(x==y)//根相同不用管 return; par[x]=y;//若根不同,y并入x,则y的根为x,同理x也能并入y 这里随意 } bool same(int x,int y)//x和y是否在一个集合 { return findr(x)==findr(y); } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&N,&M); init(N*2); char op[2]; int a,b; for(int i=0; i<M; i++) { scanf("%s%d%d", op, &a, &b); if(op[0]=='A') { if(same(a,b)) printf("In the same gang.\n"); else if(same(a,b+N)||same(a+N,b)) printf("In different gangs.\n"); else printf("Not sure yet.\n"); } else { unite(a+N,b); unite(a,b+N); } } } return 0; }