POJ 2912 Rochambeau 带权并差集(食物连变形)

来源:互联网 发布:wnba中国球员数据 编辑:程序博客网 时间:2024/06/05 02:18

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 areM 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 theM rounds of game are inconsistent, print the corresponding message.

Sample Input
3 30<11<22<03 50<10>11<21>20<24 40<10>12<32>31 0
Sample Output
Can not determinePlayer 1 can be determined to be the judge after 4 linesImpossiblePlayer 0 can be determined to be the judge after 0 lines

最近发现越来越可以脱离题解了。

我们要知道谁是裁判的话直接去判断是不好判断的,而且给出的n并不是很大,所以考虑每个人的嫌疑,枚举所有人的裁判。

这样的话 我们首先设立输赢的标志

现在有a b

如果a负b,说明b赢了 这时候我们令这两个的关系权值为1

如果a平b,这时候我们令这两个的关系权值为0

如果a胜b,说明b熟了,我们令他们的关系权值为2




初始化:

每个节点与每个节点肯定是自己与自己战平,所以关系权值初始化为0

            for(int j=0; j<n; j++)//初始化            {                pre[j]=j;                rale[j]=0;            }


关系的压缩:

如同食物连那个题目,压缩关系如下:

int findboss(int x){    if(x==pre[x])        return x;    else    {        int k=pre[x];        pre[x]=findboss(pre[x]);        rale[x]=(rale[x]+rale[k])%3;        return pre[x];    }}
关系的建立:

如果两个节点的boss不是一个人,那么就要建立关系。做一个简单的分析,关系的建立要与当前关系权值,a与boss节点的权值,b与boss节点的权值有关系。

那么可以找一下规律

如果要并入a所在的关系中,那么就要这样

                    pre[bb]=aa;                    rale[bb]=(rale[a]-rale[b]+3+c)%3;
判断:

如果两个节点boss相同就要考虑ab的关系权值是否与节点间原来的关系权值是一样的,如果不一样,那么这个人就不是裁判,同时记录下错是错在第多少组数据

                if(aa==bb)                {                    int r=(rale[b]-rale[a]+3)%3;                    if(r!=c)                    {                        wrong[i]=j+1;                        break;                    }                }

下面ac代码:

#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int rale[666],pre[666];struct aa{    int u,v;    int val;} save[2333];int findboss(int x){    if(x==pre[x])        return x;    else    {        int k=pre[x];        pre[x]=findboss(pre[x]);        rale[x]=(rale[x]+rale[k])%3;        return pre[x];    }}int wrong[666];int main(){    int n,m;    while(scanf("%d%d",&n,&m)!=EOF)    {        memset(wrong,-1,sizeof(wrong));        getchar();        for(int i=0; i<m; i++)        {            char w;            scanf("%d",&save[i].u);            scanf("%c",&w);            scanf("%d",&save[i].v);            getchar();            if(w=='<')                save[i].val=1;            else if(w=='>')                save[i].val=2;            else                save[i].val=0;        }        for(int i=0; i<n; i++)        {            for(int j=0; j<n; j++)//初始化            {                pre[j]=j;                rale[j]=0;            }            for(int j=0; j<m; j++)            {                int a=save[j].u,b=save[j].v,c=save[j].val;                if(a==i||b==i)                    continue;                int aa=findboss(a),bb=findboss(b);                if(aa==bb)                {                    int r=(rale[b]-rale[a]+3)%3;                    if(r!=c)                    {                        wrong[i]=j+1;                        break;                    }                }                else                {                    pre[bb]=aa;                    rale[bb]=(rale[a]-rale[b]+3+c)%3;                }            }        }        int cnt=0,a1=0,a2=0;        for(int i=0; i<n; i++)        {            if(wrong[i]==-1)            {                cnt++;                a1=i;            }            a2=max(a2,wrong[i]);        }        if(cnt==0) puts("Impossible");        else if(cnt>1) puts("Can not determine");        else printf("Player %d can be determined to be the judge after %d lines\n",a1,a2);    }}