POJ 2912 Rochambeau

Description:

N children are playing Rochambeau (scissors-rock-cloth) game with you. One of them is the judge. The rest children are divided into three groups (it is possible that some group is empty). You don’t know who is the judge, or how the children are grouped. Then the children start playing Rochambeau game for M rounds. Each round two children are arbitrarily selected to play Rochambeau for one once, and you will be told the outcome while not knowing which gesture the children presented. It is known that the children in the same group would present the same gesture (hence, two children in the same group always get draw when playing) and different groups for different gestures. The judge would present gesture randomly each time, hence no one knows what gesture the judge would present. Can you guess who is the judge after after the game ends? If you can, after how many rounds can you find out the judge at the earliest?

Input:

Input contains multiple test cases. Each test case starts with two integers N and M (1 ≤ N ≤ 500, 0 ≤ M ≤ 2,000) in one line, which are the number of children and the number of rounds. Following are M lines, each line contains two integers in [0, N) separated by one symbol. The two integers are the IDs of the two children selected to play Rochambeau for this round. The symbol may be “=”, “>” or “<”, referring to a draw, that first child wins and that second child wins respectively.

Output:

There is only one line for each test case. If the judge can be found, print the ID of the judge, and the least number of rounds after which the judge can be uniquely determined. If the judge can not be found, or the outcomes of the M rounds of game are inconsistent, print the corresponding message.

Sample Input:

3 3
0<1
1<2
2<0
3 5
0<1
0>1
1<2
1>2
0<2
4 4
0<1
0>1
2<3
2>3
1 0

Sample Output:

Can not determine
Player 1 can be determined to be the judge after 4 lines
Impossible
Player 0 can be determined to be the judge after 0 lines

题意:有n个人在玩剪刀石头布,其中有个人是裁判(他可以任意出剪刀石头布的一种),现在有m对两两对决的结果,判断能否在这m对结果中找到这个裁判(找到的条件当然是在有一个裁判的情况下前后结果不矛盾)。那么会产生4种结果:
1.n==1,即只有一个人,那么他肯定是裁判,输出
Player 0 can be determined to be the judge after 0 lines;
2.这m个结果完全没有矛盾,或者有矛盾,但是有好几人都满足裁判的条件,那么就不能判断谁是裁判了,输出 Can not determine;
3.这n个人无论是谁当裁判都有矛盾,那么这种情况是不可能找到裁判的,输出
Impossible;
4.满足一切情况,那么就输出 Player a can be determined to be the judge after b lines,a代表裁判的序号,b代表最早到第几行能够判断裁判是a。
#include<stdio.h>
#include<algorithm>
using namespace std;

const int N=510;

struct node
{
    int a, b, c; ///a,b是人的序号,c是a,b之间的关系
}no[N*20];
int f[N], r[N];

int Find(int x)
{
    int k = f[x];

    if (f[x] != x)
    {
        f[x] = Find(f[x]);
        r[x] = (r[x]+r[k])%3;
    }

    return f[x];
}

int Solve(int k, int n, int m) ///若是k当裁判,判断是否有矛盾,和食物链差不多
{
    int i, a, b, c, na, nb;

    for (i = 0; i < n+10; i++)
    {
        f[i] = i;
        r[i] = 0;
    }

    for (i = 0; i < m; i++)
    {
        a = no[i].a; b = no[i].b; c = no[i].c;

        if (a != k && b != k) ///因为裁判是可以任意出的,所以判断是否矛盾时要跳过裁判本身
        {
            na = Find(a); nb = Find(b);

            if (na == nb && (c+r[b])%3 != r[a]) ///出现矛盾,返回i,那么在输出最早行时就可以输出i+1了
                return i;

            f[na] = nb;
            r[na] = ((c-r[a])+r[b]+3)%3;
        }
    }

    return -1;
}

int main ()
{
    int n, m, i, p, q, s, t;
    char ch;

    while (scanf("%d%d", &n, &m) != EOF)
    {
        s = 0;

        for (i = 0; i < m; i++)
        {
            scanf("%d%c%d", &no[i].a, &ch, &no[i].b);

            if (ch == '>') no[i].c = 2; ///我们可以令>时关系为2,<时关系为1,=时关系为0(0,1,2,,,好像食物链)
            else if (ch == '<') no[i].c = 1;
            else no[i].c = 0;
        }

        p = Solve(-1, n, m); ///第一次让-1当裁判(实际上没这个人,主要是要看这m个结果中是否有矛盾)

        if (n == 1) printf("Player 0 can be determined to be the judge after 0 lines\n"); ///只有1个人,没办法,自己是裁判
        else if (p == -1 && n != 1) printf("Can not determine\n"); ///m个结果没有任何矛盾,那么就无法判断谁是裁判(好像谁都能当裁判似的)
        else
        {
            t = p; ///先保存一下产生矛盾的地方

            for (i = 0; i < n; i++)
            {
                p = Solve(i, n, m);

                if (p == -1)
                {
                    q = i; ///当i裁判时没有矛盾,要记录下来,说不定他就是真正的裁判
                    s++;
                }
                else t = max(t, p); ///要想找到裁判,必须要在所有人都判断过的情况下才行(此时其他人当裁判都会产生矛盾,那么最早发现裁判就是产生矛盾最远的地方)
                if (s > 1) break;
            }

            if (s == 1) printf("Player %d can be determined to be the judge after %d lines\n", q, t+1);
            else if (s > 1) printf("Can not determine\n");
            else printf("Impossible\n");
        }
    }

    return 0;
}
posted @ 2015-10-07 23:13  搁浅の记忆  阅读(146)  评论(0编辑  收藏  举报