zoukankan      html  css  js  c++  java
  • 【NOI2017】游戏

    题面

    https://www.luogu.org/problem/P3825

    题解

    我发现这些年我学的$2-sat$竟然一直是假的,醉了醉了。

    我们看一下$2-sat$的形式:

    如果$p$,那么$q$。

    数学上学过,一个命题成立,那么它的逆否命题成立。在这里,他的逆否命题是完全确定的。

    所以,如果非$q$,那么非$p$。

    形象理解一下,如果非$q$,那么$p$变量的值肯定不是随便取的,如果它成立,而$q$又不成立,那就假了。所以也要非$p$。

    所以在连边的时候,也要连它的“逆否边”。

    我认为,$2-sat$是可解的,和“它的逆否命题唯一确定”的性质是很有关系的,如果只连原命题的边,解集会形成一个闭合子图的形式。。。。。。。。

    对于$x$不能取$1$的情况,我们直接把$x_1$直接连到$x_0$。

    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define ri register int
    #define N 100500
    using namespace std;
    
    int n,d,m,d1[N],t1[N],d2[N],t2[N],sani,c[N],sat[N];
    int dfn[N],low[N],cnt,clo,bel[N];
    bool ins[N],vis[N];
    char s[N];
    stack<int> sta;
    vector<int> to[N];
    
    void tarjan(int x) {
      dfn[x]=low[x]=++clo;
      sta.push(x); ins[x]=1;
      for (ri i=0;i<to[x].size();++i) {
        int y=to[x][i];
        if (dfn[y]) {
          if (ins[y]) low[x]=min(low[x],dfn[y]);
        }
        else {
          tarjan(y);
          low[x]=min(low[x],low[y]);
        }
      }
      if (low[x]==dfn[x]) {
        ++cnt;
        while (1) {
          int t=sta.top(); sta.pop();
          bel[t]=cnt; ins[t]=0;
          if (t==x) break;
        }
      }
    }
    
    int fan(int x) {
      if (x>n) return x-n; else return x+n;
    }
    
    int id(int cur,int opt) {
      if ((s[cur]=='x'&&(1<<c[cur])&sani)||s[cur]=='a') {
        if (opt==2) return cur;
        if (opt==3) return cur+n;
        if (opt==1) return -1;
      }
      if ((s[cur]=='x'&&!((1<<c[cur])&sani))||s[cur]=='b') {
        if (opt==1) return cur;
        if (opt==3) return cur+n;
        if (opt==2) return -1;
      }
      if (s[cur]=='c') {
        if (opt==1) return cur;
        if (opt==2) return cur+n;
        if (opt==3) return -1;
      }
      return -1;
    }
    
    bool dfs() {
      cnt=0; clo=0;
      for (ri i=1;i<=2*n;i++) to[i].clear();
      for (ri i=1;i<=2*n;i++) dfn[i]=low[i]=0;
      memset(ins,0,sizeof(ins));
      for (ri i=1;i<=m;i++) {
        int u=id(d1[i],t1[i]),v=id(d2[i],t2[i]);
        if (u==-1) continue;
        if (v==-1) v=fan(u);
        to[u].push_back(v);
        if (v!=fan(u)) to[fan(v)].push_back(fan(u));
      }
      for (ri i=1;i<=2*n;i++) if (!dfn[i]) tarjan(i);
      for (ri i=1;i<=n;i++) if (bel[i]==bel[i+n]) return 0;
      return 1;
    }
    
    void bfs(int x) {
      if (vis[x]) return;
      vis[x]=1;
      if (x>n) {
        int cur=x-n;
        if ((s[cur]=='x'&&(1<<c[cur])&sani) || s[cur]=='a') sat[cur]=2;
        else if ((s[cur]=='x'&&!((1<<c[cur])&sani)) || s[cur]=='b') sat[cur]=2;
        else if (s[cur]=='c') sat[cur]=1;
      }
      else {
        int cur=x;
        if ((s[cur]=='x'&&(1<<c[cur])&sani) || s[cur]=='a') sat[cur]=1;
        else if ((s[cur]=='x'&&!((1<<c[cur])&sani)) || s[cur]=='b') sat[cur]=0;
        else if (s[cur]=='c') sat[cur]=0;
      }
    }
    
    void print() {
      for (ri i=1;i<=n;i++) if (bel[i]<bel[i+n]) bfs(i); else bfs(i+n);
      for (ri i=1;i<=n;i++) putchar('A'+sat[i]);
    }
    
    int main(){
      char no[5],np[5];
      scanf("%d %d",&n,&d);
      scanf("%s",s+1);
      int cc=-1;
      for (ri i=1;i<=n;++i) if (s[i]=='x') c[i]=++cc;
      scanf("%d",&m);
      for (ri i=1;i<=m;++i) {
        scanf("%d %s %d %s",&d1[i],no,&d2[i],np);
        if (no[0]=='A') t1[i]=1;
        else if (no[0]=='B') t1[i]=2;
        else if (no[0]=='C') t1[i]=3;
        if (np[0]=='A') t2[i]=1;
        else if (np[0]=='B') t2[i]=2;
        else if (np[0]=='C') t2[i]=3;
      }
      for (sani=0;sani<(1<<d);++sani) if (dfs()) {
        print();
        return 0;
      }
      printf("-1");
      return 0;
    }
  • 相关阅读:
    在安装了Anaconda+Pycharm怎么导入OpenCV
    JS--ECMAScript
    JS--DOM
    JS-BOM
    浮动 高度塌陷
    CSS2--字体样式
    CSS2--文本样式
    css2--垂直对齐
    css2--背景
    HTML基础
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11353922.html
Copyright © 2011-2022 走看看