Poj 1703 Find them, Catch them

来源:互联网 发布:it管理员 编辑:程序博客网 时间:2024/06/10 15:22

题目大意:警察抓获N个罪犯,这些罪犯只可能属于两个团伙中的其中一个,现在给出M个条件(D a b表示a和b不在同一团伙),对于每一个询问(A a b)输出a,b属于同一团伙或者不是属于同一团伙或者不能确定。

思路:并查集的应用。普通并查集相关的题目都是给出属于同一集合的元素,但是这道题是给出了属于不同集合的元素,可以维护一个opposite数组,如果x和y不属于同一集合,则将opposite[x]赋值为y。查询的时候分别判断x,y和x,opposite[y]是不是属于同一集合即可。

#include <iostream>using namespace std;#include <stdio.h>#include <memory.h>const int MAXSIZE = 500010;int rank[MAXSIZE];int parent[MAXSIZE];int opposite[MAXSIZE];int n;//集合元素,从1到nint FindSet(int x) {if (x!=parent[x])parent[x]=FindSet(parent[x]);return parent[x];}void Union(int root1, int root2) {int x=FindSet(root1),y=FindSet(root2);if (x==y)return;if (rank[x]>rank[y])parent[y]=x;else {parent[x]=y;if (rank[x]==rank[y])++rank[y];}}void Initialization() {int i;memset(rank,0,sizeof(rank));memset(opposite,0,sizeof(opposite));for (i=1;i<=n;i++) {parent[i]=i;}}int main(){int t,m,i,j;int x,y;char c;scanf("%d",&t);while (t--) {scanf("%d%d",&n,&m);Initialization();for (i=0;i<m;i++) {getchar();scanf("%c%d%d",&c,&x,&y);if (c=='D') {if (opposite[x]==0&&opposite[y]==0) {opposite[x]=y;opposite[y]=x;}else if (opposite[x]==0) {opposite[x]=y;Union(x,opposite[y]);}else if (opposite[y]==0) {opposite[y]=x;Union(y,opposite[x]);}else {Union(x,opposite[y]);Union(y,opposite[x]);}}else {if (FindSet(x)==FindSet(y))printf("In the same gang.\n");else if (FindSet(x)==FindSet(opposite[y]))printf("In different gangs.\n");else printf("Not sure yet.\n");}}}return 0;}