zoukankan      html  css  js  c++  java
  • 洛谷P3825 [NOI2017]游戏(2-SAT)

    传送门

    果然图论的题永远建图最麻烦……看着题解代码的建图过程真的很珂怕……

    先不考虑地图$x$,那么每一个地图都只能用两种赛车,于是我们可以用2-SAT来搞,用$i$表示这个地图能用的第一辆车,$i'$表示它能用的第二辆车

    至于怎么连边呢,考虑限制条件$(i,h_i,j,h_j)$,如果$i$不能用$h_i$我们直接忽视这个限制条件,如果$j$不能用$h_j$说明无解,于是我们连边$(i,i')$表示如果选了$i$的第一辆车就无解

    否则的话就按一般的2-SAT把上面的限制条件连边即可

    然后考虑怎么处理地图$x$,因为$d$最大只有$8$,且可行的方案里每一个地图$x$只要用一辆车,于是我们考虑枚举每一个地图$x$哪一辆车不能用,只需要枚举$A$和$B$即可,如果有解,能用$BC$和能用$AC$的方案里一定有一个可行

    于是时间复杂度就是$O((n+m)2^d)$

      1 //minamoto
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #define mem(a) (memset(a,0,sizeof(a)))
      6 #define swap(x,y) (x^=y^=x^=y)
      7 #define neg(x) (x>n?x-n:x+n)
      8 using namespace std;
      9 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
     10 inline int read(){
     11     #define num ch-'0'
     12     char ch;bool flag=0;int res;
     13     while(!isdigit(ch=getchar()))
     14     (ch=='-')&&(flag=true);
     15     for(res=num;isdigit(ch=getchar());res=res*10+num);
     16     (flag)&&(res=-res);
     17     #undef num
     18     return res;
     19 }
     20 inline char getc(){
     21     char ch;while((ch=getchar())!='A'&&ch!='B'&&ch!='C');return ch;
     22 }
     23 const int N=2e5+5;
     24 int head[N],Next[N],ver[N],tot;
     25 inline void add(int u,int v){
     26     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
     27 }
     28 int dfn[N],low[N],bl[N],st[N],num,cnt,top,n,m,d;
     29 void tarjan(int u){
     30     dfn[u]=low[u]=++num,st[++top]=u;
     31     for(int i=head[u];i;i=Next[i]){
     32         int v=ver[i];
     33         if(!dfn[v]) tarjan(v),cmin(low[u],low[v]);
     34         else if(!bl[v]) cmin(low[u],dfn[v]);
     35     }
     36     if(dfn[u]==low[u]) for(++cnt;st[top+1]!=u;--top) bl[st[top]]=cnt;
     37 }
     38 inline void clear(){
     39     mem(head),mem(dfn),mem(bl),mem(st);
     40     tot=num=cnt=0;
     41 }
     42 int a1[N],b1[N],Sooke[N];char s[N],a2[N],b2[N],QAQ[N];
     43 int flag=0;
     44 int tran(int x,char ch){
     45     if(s[x]=='a') return ch=='B'?x:x+n;
     46     if(s[x]=='b'||s[x]=='c') return ch=='A'?x:x+n;
     47     if(ch=='C') return x+n;return x;
     48 }
     49 bool solve(){
     50     clear();
     51     for(int i=1;i<=m;++i)
     52     if(s[a1[i]]!='x'&&s[b1[i]]!='x'){
     53         if(a2[i]==s[a1[i]]-32) continue;
     54         int u=tran(a1[i],a2[i]),v;
     55         if(b2[i]==s[b1[i]]-32){add(u,neg(u));continue;}
     56         v=tran(b1[i],b2[i]),add(u,v),add(neg(v),neg(u));
     57     }else{
     58         char o=s[a1[i]],p=s[b1[i]];
     59         int u,v,x=Sooke[a1[i]],y=Sooke[b1[i]];
     60         if(o=='x'&&p=='x'){
     61             if(a2[i]==QAQ[x]) continue;
     62             u=tran(a1[i],a2[i]);
     63             if(b2[i]==QAQ[y]){add(u,neg(u));continue;}
     64             v=tran(b1[i],b2[i]),add(u,v),add(neg(v),neg(u));
     65         }else if(o=='x'&&p!='x'){
     66             if(a2[i]==QAQ[x]) continue;
     67             u=tran(a1[i],a2[i]);
     68             if(b2[i]==s[b1[i]]-32){add(u,neg(u));continue;}
     69             v=tran(b1[i],b2[i]),add(u,v),add(neg(v),neg(u));
     70         }else{
     71             if(a2[i]==s[a1[i]]-32) continue;
     72             u=tran(a1[i],a2[i]);
     73             if(b2[i]==QAQ[y]){add(u,neg(u));continue;}
     74             v=tran(b1[i],b2[i]),add(u,v),add(neg(v),neg(u));
     75         }
     76     }
     77     for(int i=1,l=n<<1;i<=l;++i) if(!dfn[i]) tarjan(i);
     78     for(int i=1;i<=n;++i) if(bl[i]==bl[i+n]) return 0;
     79     for(int i=1;i<=n;++i)
     80     if(bl[i]<bl[i+n]){
     81         if(s[i]=='a') putchar('B');
     82         else if(s[i]=='b'||s[i]=='c') putchar('A');
     83         else if(QAQ[Sooke[i]]=='A') putchar('B');
     84         else putchar('A');
     85     }else{
     86         if(s[i]=='a'||s[i]=='b') putchar('C');
     87         else if(s[i]=='c') putchar('B');
     88         else if(QAQ[Sooke[i]]=='A') putchar('C');
     89         else putchar('B');
     90     }
     91     return 1;
     92 }
     93 void dfs(int dep){
     94     if(dep>d){
     95         if(!flag) flag=solve();
     96         if(flag) exit(0);
     97         return;
     98     }
     99     QAQ[dep]='A',dfs(dep+1);
    100     QAQ[dep]='B',dfs(dep+1);
    101 }
    102 int main(){
    103 //    freopen("testdata.in","r",stdin);
    104     n=read(),read();
    105     scanf("%s",s+1),m=read();
    106     for(int i=1;i<=n;++i) if(s[i]=='x') Sooke[i]=++d;
    107     for(int i=1;i<=m;++i)
    108     a1[i]=read(),a2[i]=getc(),b1[i]=read(),b2[i]=getc();
    109     dfs(1);
    110     if(!flag) printf("%d",-1);
    111     return 0;
    112 }
  • 相关阅读:
    175. 组合两个表
    101. 对称二叉树
    292. Nim游戏
    319. 灯泡开关
    155. 最小栈
    232. 用栈实现队列
    225. 用队列实现栈
    145. 二叉树的后序遍历
    144. 二叉树的前序遍历
    【leetcode】977. Squares of a Sorted Array
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9786225.html
Copyright © 2011-2022 走看看