标签:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 34672 | Accepted: 10691 |
1
5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4
Not sure yet.
In different gangs.
In the same gang.
题解:并查集经典题,很不错。本来觉得是把并查集的过程反过来,并用一个bool数组记录i这个人有没有操作过,操作过才能知道他的阵营,否则不能,但是后来发现这显然是错了,还有很多不能确定。后来看了看别人的做法,突然发现当D时,只需要把x和y的敌人合并,y和x的敌人合并,而i的敌人只需要用一个数组记录一下就可以了。而查询时,如果find(x)与y在一个联通块则是一个,如果和对方的敌人是一个联通块怎不是一个,否则则无法判断。
CODE:
#include <iostream> #include <cstdio> #include <cstring> #define REP(i, s, n) for(int i = s; i <= n; i ++) #define REP_(i, s, n) for(int i = n; i >= s; i --) #define MAX_N 100000 + 10 using namespace std; int n, q, F[MAX_N], E[MAX_N]; int find(int x){ if(F[x] == x) return x; return F[x] = find(F[x]); } void Union(int x,int y){ x = find(x), y = find(y); if(x == y) return; F[y] = x; } int main(){ int T; scanf("%d", &T); while(T --){ scanf("%d%d", &n, &q); REP(i, 1, n) F[i] = i, E[i] = 0; char s[3]; int x, y; while(q --){ scanf("%s", s); if(s[0] == ‘A‘){ scanf("%d%d", &x, &y); if(find(x) == find(y)) printf("In the same gang.\n"); else if(find(x) == find(E[y])) printf("In different gangs.\n"); else printf("Not sure yet.\n"); } else if(s[0] == ‘D‘){ scanf("%d%d", &x, &y); if(!E[x] && !E[y]) E[x] = y, E[y] = x; else if(!E[x]) E[x] = y, Union(x, E[y]); else if(!E[y]) E[y] = x, Union(y, E[x]); else if(E[x] && E[y]) Union(x, E[y]), Union(y, E[x]); } } } return 0; }
POJ 1703 Find them, Catch them
标签:
原文地址:http://www.cnblogs.com/ALXPCUN/p/4552293.html