1. 程式人生 > >洛谷P3825 [NOI2017]遊戲(2-SAT)

洛谷P3825 [NOI2017]遊戲(2-SAT)

open while 怎麽 == sdi get style pre else

傳送門

果然圖論的題永遠建圖最麻煩……看著題解代碼的建圖過程真的很珂怕……

先不考慮地圖$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 }

洛谷P3825 [NOI2017]遊戲(2-SAT)