POj 1703 Find them, Catch them(关系并查集)

题目: 戳我

题意:城市中有两个社会团伙

已知有n个人:编号为1~n,和m个信息

对于每个信息,D a b表明a和b属于不同的团伙,并且信息不会相互矛盾;A a b表示讯问a和b的关系,

要求依次回答每个讯问,回答形式如下:

Not sure yet.       //a和b的关系不确定

In different gans.  //a和b属于不同的团伙

In the same gang. //a和b属于同一个团伙

回顾并查集的合并操作:我们总是将同类的集合进行合并,但此题给出的却是不同类的两个元素。

抓住关键,城市的团伙只有两个,这个信息告诉我们:如果a和b不同类,b和c不同类,那么a和c必然属于一个团伙。

更一般的,如果我们把编号看做顶点,关系看做连边。那么,如果顶点a,b之间的路径包含奇数条边,那么a与b属于不同的团伙,如果a,b之间的路径包含偶数条边,那么a与b属于同一个团伙。

我们能够很容易的计算出元素x与根节点的“距离”(即路径上经过的边数)dis[x]。类似的,对于与x同属一个集合的任意元素y,我们也可以计算出y与根节点的“距离”dis[y]。那么,x与y的“距离”便可以用dis[x]+dis[y]表示。(注意,我们只关心“距离”的奇偶性,并不关心“距离”是否是最短的)

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>

using namespace std;

const int inf = 0x3f;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5+5;

int bleg[maxn], dis[maxn], n, q;

int find(int x)
{
    int y = x, cnt = 0;
    while(y != bleg[y])
    {
        cnt += dis[y];
        y = bleg[y];
    }
    while(x != bleg[x])
    {
        int px = bleg[x], tmp = dis[x];
        dis[x] = cnt;
        bleg[x] = y;
        cnt -= tmp;
        x = px;
    }
    return y;
}

void Union(int a, int b)
{
    int pa = find(a), pb = find(b);
    if(pa == pb) return;
    dis[pa] = dis[a] + dis[b] + 1;
    bleg[pa] = pb;
}

void Init()
{
    for(int i = 0; i <= n; i++)
    {
        bleg[i] = i; dis[i] = 0;
    }
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %d", &n, &q);
        Init();
        while(q--)
        {
            int x, y;
            char op;
            scanf(" %c %d %d", &op, &x, &y);
            if(op == 'A')
            {
                int pa = find(x), pb = find(y);
                if(pa != pb)
                {
                    puts("Not sure yet.");
                }
                else if((dis[x] + dis[y]) % 2 != 0)
                {
                    puts("In different gangs.");
                    //printf("%d %d\n", dis[x], dis[y]);
                }
                else 
                {
                    puts("In the same gang.");
                }
            }
            else 
            {
                Union(x, y);
            }
        }
    }
    return 0;
}

  

posted @ 2015-06-02 21:49  豪气干云  阅读(270)  评论(0编辑  收藏  举报