POJ 1703

来源:互联网 发布:免费办公用品软件系统 编辑:程序博客网 时间:2024/05/17 02:37

    一道很好的题目,和POJ食物链那题解法一样,虽然AC了其实还是不能深入了解其本质,只能在这里谈一谈表象。
    通过读题我们可以发现可以从两组信息中推断出新的信息,例如:输入中有D 1 2D 2 3,我们可以得知1和3是同一组的。因此我们需要一种数据结构能够维护给出的关系,并且帮助我们保存推断出的关系。如果我是第一次听到这个需求,我肯定认为这种数据结构不存在,或者至少实现起来很复杂,不过其实有一种很简单的数据结构就可以做到,那就是——并查集。个人觉得很难理解为什么并查集能够做到这些,可是事实的确如此。
    要做到这个,首先我们要对标号进行一个小处理,即假设1属于A组(代指题目中的Gang Dragon),那么标号不变,如果1属于B组( Gang Snake),那么标号加上n。要注意,对于题目给出的编号来说,我们既可以将其归为A组,也可以将其归为B组,所以我们两个假设都处理。如果题目给出D 1 2,那么我们就将1和2+n合并为一个集合,然后再将1+n和2合并为另一个集合,对于D 2 3同样,此时一个集合为(1, 2+n, 3),另一个集合为(1+n, 2, 3+n),我们可以发现题目中给出的关系和推断出的关系都保存下来了。
    对于A 1 3来说,由于上述两个集合是等价的,所以可以简单假设1属于A组, 3属于B组或1属于A组, 3属于A组来判断,而不需要反过来再检查一遍。
    那也许有人会认为假设1属于A组,2属于B组不就好了吗?但是如果遇到如下输入,你的假设就可能导致错误结果:

D 1 2
D 2 3
D 4 5
D 5 6
A 3 4

代码(G++):

#include <iostream>#include <cstdio>#include <cstring>#define MAXN 100000using namespace std;int pre[MAXN*2+5];int find(int a){    if(pre[a] != a) pre[a] = find(pre[a]);    return pre[a];}void unite(int a, int b){    int pa, pb;    pa = find(a);    pb = find(b);    if(pa != pb) pre[pa] = pb;}bool same(int a, int b){    int pa, pb;    pa = find(a);    pb = find(b);    if(pa == pb) return true;    else return false;}int main(){    int t, n, m, a, b;    char ch;    scanf("%d", &t);    while(t--)    {        scanf("%d %d", &n, &m);        for(int i=1; i<=n*2; i++) pre[i] = i;        for(int i=0; i<m; i++)        {            scanf("%c", &ch);            scanf("%c %d %d", &ch, &a, &b);            if(ch == 'D')            {                unite(a, b+n);                unite(a+n, b);            }else{                if(same(a, b)) printf("In the same gang.\n");                else if(same(a, b+n)) printf("In different gangs.\n");                else printf("Not sure yet.\n");            }        }    }    return 0;}

题目:

Find them, Catch themTime Limit: 1000MS      Memory Limit: 10000KDescriptionThe 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. InputThe 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.OutputFor 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 Input15 5A 1 2D 1 2A 1 2D 2 4A 1 4Sample OutputNot sure yet.In different gangs.In the same gang.
0 0