zoukankan      html  css  js  c++  java
  • POJ 2912 Rochambeau(暴力)+【带权并查集】

    <题目链接>

    题目大意:

    n个人进行m轮剪刀石头布游戏(0<n<=500,0<=m<=2000),接下来m行形如x, y, ch的输入,ch='='表示x, y平局,ch='>'表示x赢y,ch='<'表示x输y, 但是我们不知道x, y的手势是什么; 其中有一个人是裁判,它可以出任意手势,其余人手势相同的分一组,共分为三组,可以存在空组,也就是说除了裁判外,其余人每一次出的手势都相同,问能不能确定裁判是几号,如果能,输出最少在第几轮可以确定;

    解题分析:

    由于直接对所给的条件进行并查集处理,不容易直接找出符合要求的裁判,所以我们不妨暴力枚举裁判,因为裁判可以随便出,所以包含裁判的语句要直接跳过,不能作为判断冲突的条件,然后我们就可以遍历所有的条件,如果在当前遍历的裁判情况下,这些语句不产生冲突,说明当前遍历的裁判是可行的,裁判数量+1。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N = 500+5;
    const int M = 2e3+10;
    int rnk[N],father[N];
    int arr[M],brr[M],n,m;
    char ss[M];
    void init(){
        for(int i=0;i<n;i++){
            father[i]=i;
            rnk[i]=0;
        }
    }
    int find(int x){
        if(father[x]==x)return x;
        int tmp=father[x];
        father[x]=find(father[x]);
        rnk[x]=(rnk[x]+rnk[tmp]+3)%3;
        return father[x];
    }
    int Union(int a,int b,int c){
        int ra=find(a),rb=find(b);
        if(ra==rb){    //如果根相同就直接判断是否冲突
            if((rnk[a]-rnk[b]+3)%3!=c)return 1;   //冲突
            return 0;
        }
        father[ra]=rb;
        rnk[ra]=(c-rnk[a]+rnk[b]+3)%3;   //利用矢量,构造ra-->rb之间的rnk关系
        return 0;
    }
    int main(){
        while(scanf("%d%d",&n,&m)!=EOF){
            for(int i=1;i<=m;i++){
                scanf("%d%c%d",&arr[i],&ss[i],&brr[i]);
            }
            int num=0,loc=0,ord=0;
            for(int i=0;i<n;i++){   //暴力枚举裁判
                init();
                bool flag=true;
                for(int j=1;j<=m;j++){
                    if(arr[j]==i||brr[j]==i)continue;   //因为裁判可以任意出,不会与其他人产生冲突,所以遇到裁判就跳过 
                    int c;
                    if(ss[j]=='=')c=0;
                    else if(ss[j]=='<')c=1;
                    else c=2;
                    if(Union(arr[j],brr[j],c)){   //判断是否出现矛盾
                        loc=max(j,loc);   //(难点)维护矛盾出现的最大行数,因为如果最后只有一个裁判的话,说明其他的都不是裁判,而这里记录的每个枚举出的裁判出现矛盾的最小行数,所以,最后如果要使这些裁判全部出现矛盾的话,就记录下这些最小行数的最大值
                        flag=false;
                        break;
                    }
                }
                if(flag){
                    num++; //如果没有矛盾,说明这个人可以为裁判
                    ord=i; //记录下裁判的序号
                }
            }
            if(!num)printf("Impossible
    ");
            else if(num>1)printf("Can not determine
    ");
            else printf("Player %d can be determined to be the judge after %d lines
    ", ord, loc);
        }
        return 0;
    }

    2018-10-03

  • 相关阅读:
    JS高阶---继承模式(原型链继承)
    一切皆数据,人生需学习
    操作系统升级
    看了跨年演讲后
    新的开始
    怎么做一名高薪前端工程师,必备哪些技术工具?
    web服务器 Nginx
    实用的软件架构方法
    购买网络自动化工具时应考虑的7个方面
    ES6 展开操作符的几个妙用
  • 原文地址:https://www.cnblogs.com/00isok/p/9741331.html
Copyright © 2011-2022 走看看