zoukankan      html  css  js  c++  java
  • P3825 [NOI2017]游戏

    题目链接:https://www.luogu.com.cn/problem/P3825

    我太蠢了呀。

    题意读错想半天。蠢的跟猪一样。

    最后看了题解才晓得题意读错了,猪,你为何这么蠢。

    先来个题意知识:

    小 L 对游戏有一些特殊的要求,这些要求可以用四元组 (i,hi,j,hj)来描述,表示若在第i场使用型号为hi的车子,则第j场游戏要使用型号为hj的车子。

    这句话的意思应该是在第i场选择了hi的时候,则第j场必须选择hj。

    但是是建了反向边的呢?也就是说: 若两个都可用,则从i向j连边,表示若选i,则一定选j,同时从j′向i′连边,这里表示若没有选j,则一定没有选i。

    为啥没有选hj,则i那个位置不能选hi呢?题目只是说i选择了hi,则j必须选择hj呀。我相信有部分同学会有这个困惑。

    解释:

    如何证明原命题与其逆否命题具有相同的真假性,请给出证明
    用反证法
    设原命题为“若p则q”,则逆否命题为“若非q则非p”
    假设“原命题与其逆否命题具有相同的真假性”错误
    则有“若p→q为真,则 非q→非p为假”
    或“若p→q为假,则 非q→非p为真”
    1,若p→q为真,则 非q→非p为假
    因为非q→非p为假,所以非q→p为真 这与 p→q为真 矛盾
    2,若p→q为假,则 非q→非p为真
    因为p→q为假,所以p→非q为真 这与 非q→非p为真 矛盾
    所以假设均不成立,所以原命题与其逆否命题具有相同的真假性,得证.
    反证法成立的原理就是逆否命题和原命题等价?
    你瞎说什么呢.
    反证法是排除其它一切可能,只剩这一种可能,和逆否命题和原命题等价一点关系都没有的好吧
    证明链接:https://www.zybang.com/question/2622b4d2c390a64ddaee7580b5b23ac5.html
    这里主要是原命题和逆否命题的知识;
    我们考虑一下当d为0的时候:
    那么,每个地图最多会有两辆车子。而且每个地图一定是会从中选取一辆车。
    那这也就是一个2-SAT问题的模板了。只是说我们要仔细考虑。
    如果xi地图为B,则i表示选择A车,i+n表示选择C车
    如果地图为C,则i表示选择A车,i+n表示选择B车
    如果地图为A,则i表示选择B车,i+n表示选择C车。
    考虑建边问题:
    对于一个四元组(i,hi,j,hj)
    如果str[i]==hi,则表示地图i中,根本不可能选择hi这辆车,那这个直接continue就好。
    在上面条件不满足情况下,如果str[j]==hj,则表示,j这个位置一定不可以选择hj这辆车。那么我们可以把i和i+n进行连接,表示如果i这个位置选择了hi,则也一定要选择i’。
    在上面条件都不满足情况下,也就是说i这个为位置可以选择hi,j这个位置可以选择hj。
    那我肯定要i指向j的位置。同时因为逆否命题,我要j'指向i'这个位置。
    然后观察得到d值较小。我们可以直接枚举每个X位置会为什么情况。
    理论上,我们需要枚举每个x位置分别为A,B,C 的情况
    也就是:
    1,x位置为A,则可选车为B和C
    2,x位置为B,则可选车为A和C
    3,x位置为C,则可选车为A和B
    我们可以发现,第一种和第二种其实已经包含了第三种。
    所以我们只要枚举两种情况即可。
        #include"stdio.h"
        #include"string.h"
        #include"vector"
        #include"algorithm"
        using namespace std;
        #define OK printf("
    ");
        #define exit return 0;
        const int N = 1e6 * 2 + 1010;
        const int M = 2 * N;
        int read()
        {
            int f=1,x=0;
            char ss=getchar();
            while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
            while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
            return f*x;
        }
        int head[N],ver[M],Next[M],tot;int n,m,num,top,cnt;
        int dfn[N],low[N],id[110];int limit = 0;
        int Stack[N],ins[N],c[N];
        int s[N];  char str[N];
        int X[N],Y[N]; char cx[N],cy[N];
    
        void add(int x,int y){
            ver[++ tot] = y; Next[tot] = head[x];
            head[x] = tot;
        }
    
        void tarjan(int x){
            dfn[x] = low[x] = ++ num;
            Stack[++ top] = x; ins[x] = 1;
            for(int i = head[x]; i; i = Next[i])
                if(!dfn[ver[i]]) {
                    tarjan(ver[i]);
                    low[x] = min(low[x],low[ver[i]]);
                } else if(ins[ver[i]])
                 low[x] = min(low[x],dfn[ver[i]]);
            if(dfn[x] == low[x]){
                cnt ++; int y;
                do{
                    y = Stack[top --];ins[y] = 0;
                    c[y] = cnt;
                } while(x != y);
            }
        }
    
        void Build_edge()
        {
           for(int i = 1; i <= m; i ++){
                if(str[X[i]] == cx[i]) continue;
                if(str[Y[i]] == cy[i]) {
                    if(cx[i] == 'C' || (cx[i] == 'B' && str[X[i]] == 'C')) {
                       add(X[i] + n,X[i]); //printf("%d -> %d
    ",X[i] + n,X[i]);
                    } else {
                        add(X[i],X[i] + n); //printf("%d -> %d
    ",X[i],X[i] + n);
                    }
                    continue;
                }
                int v1 = (cy[i] == 'C' || (cy[i] == 'B' && str[Y[i]] == 'C')) ? 1 : 0;
                int v2 = (cx[i] == 'C' || (cx[i] == 'B' && str[X[i]] == 'C')) ? 1 : 0;
                add(X[i] + n * (v2),Y[i] + n * v1);
                add(Y[i] + n * (v1 ^ 1),X[i] + n * (v2 ^ 1));
               // printf("%d -> %d
    ",X[i] + n *(v2),Y[i] + n * v1);
              //  printf("%d -> %d
    ",Y[i] + n * (v1 ^ 1),X[i] + n * (v2 ^ 1));
            }
            return ;
        }
        void init()
        {
            num = 0; memset(ins,0,sizeof(ins));
            cnt = 0; tot = 0; top = 0;
            memset(low,0,sizeof(low)); memset(c,0,sizeof(c));
            memset(dfn,0,sizeof(dfn));memset(Stack,0,sizeof(Stack));
            memset(head,0,sizeof(head));
        }
        void solve(){
    
            int mark = 1;
            for(int i = 0; i < (1 << limit); i ++){
                init();mark = 1;
                for(int j = 1; j <= limit; j ++){
                    str[id[j]] = (i & (1 << (j - 1))) ? 'A' : 'B';
                }
                Build_edge();
                for(int i = 1; i <= n * 2; i ++){
                    if(!dfn[i]) tarjan(i);
                }
                for(int i = 1; i <= n; i ++)
                  if(c[i] == c[i + n]) {mark = 0; break;}
                if(mark == 0) continue;
                for(int i = 1; i <= n; i ++){
                    if(c[i] < c[i + n]){
                        if(str[i] == 'A') printf("B");
                        else printf("A");
                    } else {
                        if(str[i] == 'C') printf("B");
                        else printf("C");
                    }
                }
                return ;
            }
            printf("-1"); return ;
        }
        int main()
        {
            int d;
            scanf("%d%d",&n,&d);
            scanf("%s",str + 1);
            for(int i = 1; i <= n; i ++)
             {
                 if(str[i] == 'x') id[++ limit] = i;
                 else str[i] -= 32;
             }
            m = read();
            for(int i = 1; i <= m; i ++){
               scanf("%d %c %d %c",&X[i],&cx[i],&Y[i],&cy[i]);
            }
            solve();
            return 0;
        }
    
  • 相关阅读:
    主流ORM对比分析,莫人云亦云
    避免远程调用中固有的滞后时间问题的最佳方法是进行更少的调用,并让每个调用传递更多的数据。
    挣值管理(PV、EV、AC、SV、CV、SPI、CPI) 记忆
    项目成本管理记忆口诀:
    总是差和自由时差
    成本基线
    php htmlentities函数的问题
    .NET简谈事务、分布式事务处理
    Startup配置类 居然又是约定
    项目管理的九大只是领域输入,工具和输出
  • 原文地址:https://www.cnblogs.com/yrz001030/p/12428049.html
Copyright © 2011-2022 走看看