poj 2912 - Rochambeau(并查集)

题意、思路:
     跟poj1182食物链题意题意几乎是一样的,那个题目的意思是a吃b,b吃c,c吃a,而这个是剪子包袱锤,所以说是一样的。只需要把这个题的数据稍微变换一下,【把这道题目的的"a>b"和"a<b"变成那个题的(1 a b),(1 b a)即可】,就不用推新的公式了,那么集合合并和路径压缩的公式还是用原来的就可以了。
     不同的是这道题目需要用多次并查集。对于这个题我们的做法是,枚举每个小孩为judge,并记录他为judge时在第几句话出错(即到第几句话能判断该小孩不是judge)。
       1. 如果只有1个小孩是judge时全部语句都是正确的,说明该小孩是judge,那么判断的句子数即为其他小孩的出错位置的最大值。如果
       2. 如果每个小孩的都不是judge(即都可以找到出错的语句),那么就是impossible。
       3. 多于1个小孩是judge时没有找到出错的语句,就是Can not determine。

代码如下:

const int M = 2005;
const int N = 505;
struct Rec
{
    int a, b, o;
}rec[M];
int p[N], flag[N];
int find(int x)
{
    int tmp = p[x];
    p[x] = (p[x]==x?x:find(p[x]));
    flag[x] = (flag[tmp]+flag[x])%3;
    return p[x];
}
int main()
{
    int n, m, a, b;
    char tmp;
    while(~scanf("%d%d", &n, &m))
    {
        for(int i = 0; i < m; ++i)
        {
            scanf("\n%d%c%d", &a, &tmp, &b);
            rec[i].o = (tmp=='='?1:2);
            if(tmp=='>')
                rec[i].a = a, rec[i].b = b;
            else
                rec[i].a = b, rec[i].b = a;
        }
        int ansi, ansm = 0, cnt = 0;
        for(int i = 0; i < n; ++i)
        {
            int isBreak = 0;
            memset(flag,0,sizeof(flag));
            for(int j = 0; j < n; ++j) p[j] = j;
            for(int j = 0; j < m; ++j)
            {
                if(rec[j].a==i||rec[j].b==i) continue;
                int a = rec[j].a;
                int b = rec[j].b;
                int o = rec[j].o;
                int x = find(a);
                int y = find(b);
                if(x==y && (flag[b]-flag[a]+o)%3!=1)
                {
                    isBreak = j+1;
                    break;
                }
                else if(x != y)
                {
                    p[x] = y;
                    flag[x] = (flag[b]-flag[a]+2+o)%3;
                }
            }
            if(isBreak) ansm = max(ansm,isBreak);
            else ansi = i, cnt += 1;
        }
        if(cnt==0) printf("Impossible\n");
        else if(cnt>1) printf("Can not determine\n");
        else printf("Player %d can be determined to be the judge after %d lines\n", ansi, ansm);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值