poj 1703 Find them, Catch them 并查集

来源:互联网 发布:哈尔滨理工大学网络课 编辑:程序博客网 时间:2024/06/03 20:32

题目

题目链接:http://poj.org/problem?id=1703

题目来源:《挑战》练习题

简要题意:N个帮派可能属于两个大帮派,给定M个询问,给出两个帮敌对,或者询问两个帮的关系。

数据范围:N105;M105

题解

这个和挑战上给出的例题非常相似,但是相比之下会简单不少。

扩大fa数组,变为两倍,然后n+x表示x的敌对关系。

对于敌对的话就是去合并x,y+n还有x+n,y,我的他的敌对一类,我的敌对和他一类。

查询的时候x,y一类就是一帮,x,y+n一类就是敌对,否则就是不确定。

代码

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>#include <stack>#include <queue>#include <string>#include <vector>#include <set>#include <map>#define pb push_back#define mp make_pair#define all(x) (x).begin(),(x).end()#define sz(x) ((int)(x).size())#define fi first#define se secondusing namespace std;typedef long long LL;typedef vector<int> VI;typedef pair<int,int> PII;LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}// headconst int N = 100000+5;int r[N*2];int fa[N*2];int find(int key) {    return (key == fa[key]) ? key : (fa[key] = find(fa[key]));}void init(int n) {    for (int i = 1; i <= n; i++) {        r[i] = 0;        fa[i] = i;    }}void joint(int u, int v) {    int a = find(u), b = find(v);    if (a != b) {        if (r[a] > r[b]) swap(a, b);        fa[a] = b;        if (r[a] == r[b]) r[b]++;    }}bool same(int u, int v) {    return find(u) == find(v);}char s[5];char out[3][25] = {"Not sure yet.", "In different gangs.", "In the same gang."};int main(){    int t, n, m, u, v;    scanf("%d", &t);    while (t--) {        scanf("%d%d", &n, &m);        init(n*2);        for (int i = 0; i < m; i++) {            scanf("%s%d%d", s, &u, &v);            if (s[0] == 'A') {                if (same(u, v)) {                    puts(out[2]);                } else if (same(u, v+n)) {                    puts(out[1]);                } else {                    puts(out[0]);                }            } else {                joint(u, n+v);                joint(v, n+u);            }        }    }    return 0;}
0 0