poj 1703 Find them, Catch them 【带权并查集】

Find them, Catch them
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 34621   Accepted: 10675

Description

The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, the police first needs to identify which gang a criminal belongs to. The present question is, given two criminals; do they belong to a same clan? You must give your judgment based on incomplete information. (Since the gangsters are always acting secretly.)

Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds:

1. D [a] [b]
where [a] and [b] are the numbers of two criminals, and they belong to different gangs.

2. A [a] [b]
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang.

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case begins with a line with two integers N and M, followed by M lines each containing one message as described above.

Output

For each message "A [a] [b]" in each case, your program should give the judgment based on the information got before. The answers might be one of "In the same gang.", "In different gangs." and "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.
同1182思路。给出两种代码
对于每只动物创建2个元素i-A,i-B,并用这2 乘 N 个元素建立并查集。
这个并查集维护如下信息: 
1,i-x 表示i属于种类x 。
2,并查集里的每一组表示组内所有元素代表的情况都同时发生或不发生。 
例如,如果i-A和i-B在同一个组里,就表示如果i属于种类A那么j一定属于种类B,如果j属于种类B那么i一定属于种类A。
因此,对于每一条信息,只需要按照下面进行操作就可以了。 
第一种:x和y属于异类 合并x-A和y-B,x-B和y-A;(x代表x-A,x+n代表x-B) 
第二种:查询,判断x-A和y-A,x-A和y-B; 
#include <cstdio>
#include <cstring>
#define MAX 200000+10
using namespace std;
int set[MAX];
int n, m;
void init()
{
    for(int i = 1; i <= 2*n; i++)
    set[i] = i;
}
int find(int p)
{
    int t;
    int child = p;
    while(p != set[p])
    p = set[p];
    while(child != p)
    {
        t = set[child];
        set[child] = p;
        child = t;
    }
    return p;
}
void merge(int x, int y)
{
    int fx = find(x);
    int fy = find(y);
    if(fx != fy)
    set[fx] = fy;
}
bool same(int x, int y)
{
    return find(x) == find(y);
}
void slove()
{
    int x, y; 
    char a[2];
    while(m--)
    {
        scanf("%s%d%d", a, &x, &y);
        if(a[0] == 'D')
        {
            merge(x+n, y);
            merge(x, y+n);
        }
        else if(a[0] == 'A')
        {
            if(same(x, y))
            printf("In the same gang.\n");
            else if(same(x, y+n))
            printf("In different gangs.\n");
            else
            printf("Not sure yet.\n");
        } 
    }
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &m);
        init();
        slove();
    }
    return 0;
} 

代码二:

 

#include <cstdio>
#include <cstring>
#define MAX 100000+10
using namespace std;
int set[MAX];
int vis[MAX];//记录动物i 第一次出现时 与它不同种类的动物 
int n, m;
void init()
{
    for(int i = 1; i <= n; i++)
    {
        set[i] = i;
        vis[i] = 0;
    }
}
int find(int p)
{
    int t;
    int child = p;
    while(p != set[p])
    p = set[p];
    while(child != p)
    {
        t = set[child];
        set[child] = p;
        child = t;
    }
    return p;
}
void merge(int x, int y)
{
    int fx = find(x);
    int fy = find(y);
    if(fx != fy)
    set[fx] = fy;
}
bool same(int x, int y)
{
	return find(x) == find(y); 
}
void slove()
{
    int x, y; 
    char a[2];
    while(m--)
    {
        scanf("%s%d%d", a, &x, &y);
        if(a[0] == 'A')
        {
            if(same(x, y))
            printf("In the same gang.\n");
            //else if(!vis[x] && !vis[y]) 
            else if(same(x, vis[y]))//此处不能用 vis[x] vis[y]判断 WA到死,改一下就过了。 求指教
            printf("In different gangs.\n");
            else 
        	printf("Not sure yet.\n");
        }
        else if(a[0] == 'D')
        {
            if(vis[x])//没有出现过
            {
                merge(vis[x], y); //合并vis[x] 和 y 
            }
            else
            vis[x] = y;
            if(vis[y])
            {
                merge(vis[y], x);
            }
            else
            vis[y] = x;
        }
    }
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &m);
        init();
        slove();
    }
    return 0;
} 



 

你可能感兴趣的:(poj 1703 Find them, Catch them 【带权并查集】)