Luogu3825 NOI2017 遊戲 2-SAT
阿新 • • 發佈:2019-02-05
() its rand ons 遊戲 stdout clu shuf signed
傳送門
第一眼看上去似乎是一個3-SAT問題
然而\(d \leq 8\)給我們的信息就是:暴力枚舉
枚舉\(x\)型地圖變成\(a\)型地圖還是\(b\)型地圖(實際上不要枚舉\(c\),因為\(ab\)兩種地圖已經包含了選擇\(ABC\)三輛車的情況),對於每一種情況跑2-SAT即可。復雜度\(O(2^d(n+m))\)
還有為什麽UOJ的Hack那麽強啊QAQ
隨機化要麽WA EX5要麽WA EX8,不隨機化TLE EX9
#include<bits/stdc++.h> //This code is written by Itst using namespace std; inline int read(){ int a = 0; char c = getchar(); bool f = 0; while(!isdigit(c)){ if(c == ‘-‘) f = 1; c = getchar(); } while(isdigit(c)){ a = (a << 3) + (a << 1) + (c ^ ‘0‘); c = getchar(); } return f ? -a : a; } const int MAXN = 2e5 + 3 , T = 190; struct Edge{ int end , upEd; }Ed[MAXN << 1]; int head[MAXN] , dfn[MAXN] , low[MAXN] , in[MAXN] , st[MAXN] , ban[MAXN]; int cntEd , top , ts , cntX , N , M , scc , x[9] , ys[MAXN][4]; char s[MAXN]; bool ins[MAXN]; inline void addEd(int a , int b){ Ed[++cntEd].end = b; Ed[cntEd].upEd = head[a]; head[a] = cntEd; } inline char getc(){ char c = getchar(); while(!islower(c)) return c; return c; } void tarjan(int x){ dfn[x] = low[x] = ++ts; ins[x] = 1; st[++top] = x; for(int i = head[x] ; i ; i = Ed[i].upEd){ if(!dfn[Ed[i].end]) tarjan(Ed[i].end); else if(!ins[Ed[i].end]) continue; low[x] = min(low[x] , low[Ed[i].end]); } if(dfn[x] == low[x]){ ++scc; do{ ins[st[top]] = 0; in[st[top]] = scc; }while(st[top--] != x); } } #define calc(ys , p) ((ys) + ((p) == 2 - (ban[ys] == 2)) * N) bool solve(){ memset(dfn , 0 , sizeof(int) * (N * 2 + 1)); memset(head , 0 , sizeof(int) * (N * 2 + 1)); cntEd = ts = scc = 0; for(int i = 1 ; i <= M ; ++i){ if(ban[ys[i][0]] == ys[i][1]) continue; if(ban[ys[i][2]] == ys[i][3]){ addEd(calc(ys[i][0] , ys[i][1]) , calc(ys[i][0] , 3 - ban[ys[i][0]] - ys[i][1])); continue; } int p = calc(ys[i][0] , ys[i][1]) , q = calc(ys[i][2] , ys[i][3]); addEd(p , q); addEd(q + (q > N ? -N : N) , p + (p > N ? -N : N)); } for(int i = 1 ; i <= N * 2 ; ++i) if(!dfn[i]) tarjan(i); for(int i = 1 ; i <= N ; ++i) if(in[i] == in[i + N]) return 0; return 1; } deque < int > q; int main(){ #ifndef ONLINE_JUDGE //freopen("in" , "r" , stdin); //freopen("out" , "w" , stdout); #endif srand((unsigned)time(0)); N = read(); read(); scanf("%s" , s + 1); for(int i = 1 ; i <= N ; ++i) if(s[i] == ‘x‘) x[cntX++] = i; else ban[i] = s[i] - ‘a‘; M = read(); for(int i = 1 ; i <= M ; ++i){ ys[i][0] = read(); ys[i][1] = getc() - ‘A‘; ys[i][2] = read(); ys[i][3] = getc() - ‘A‘; } for(int i = 0 ; i < 1 << cntX ; ++i) q.push_back(i); srand((unsigned)time(0)); random_shuffle(q.begin() , q.end()); for(int i = T ; i >= 0 && !q.empty() ; --i){ int t = q.front(); q.pop_front(); random_shuffle(q.begin() , q.end()); for(int j = 0 ; j < cntX ; ++j) ban[x[j]] = (bool)(t & (1 << j)); if(solve()){ for(int j = 1 ; j <= N ; ++j) switch(ban[j]){ case 0: putchar(‘B‘ + (in[j] > in[j + N])); break; case 1: putchar(‘A‘ + (in[j] > in[j + N]) * 2); break; case 2: putchar(‘A‘ + (in[j] > in[j + N])); } return 0; } } printf("-1"); return 0; }
Luogu3825 NOI2017 遊戲 2-SAT