BZOJ4945 & 洛谷3825 & UOJ317:[NOI2017]游戏——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4945
https://www.luogu.org/problemnew/show/P3825
题目不粘了。
对于冲突关系很明显是2-SAT,但是注意是2-SAT(lz曾经天真的gg过),也就是说,我们没法处理x。
不用慌,我们完全可以O(3^d)枚举,然而常数很大过不去uoj的hack。
但是思考如果为A则只可以选b/c,B则只可以选a/c,所以选C的情况已经被前面讨论完了,故可以O(2^d)枚举。
另外加点常数优化,比如if语句写else之类的TAT浪费我30min的时间卡常。
#include<cmath> #include<stack> #include<vector> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=5e4+5; const int M=1e5+5; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } inline int getc(){ char ch; while((ch=getchar())==' '||ch=='\n'); if(ch=='A'||ch=='a')return 0; if(ch=='B'||ch=='b')return 1; if(ch=='C'||ch=='c')return 2; return 3; } struct data{ int x,l,y,r; }p[M]; struct node{ int to,nxt; }e[M<<1]; int n,d,m,cnt,head[N<<1],to[N<<1],a[N],mp[10]; int dfn[N<<1],low[N<<1],t,l; bool inq[N<<1]; stack<int>q; inline void add(int u,int v){ e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt; } void tarjan(int u){ dfn[u]=low[u]=++t; q.push(u);inq[u]=1; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); }else if(inq[v]){ low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]){ int v;l++; do{ v=q.top();q.pop(); to[v]=l;inq[v]=0; }while(v!=u); } } inline int g(int x){ if(x>=3)x-=3; return x; } inline int f(int x){ if(x>n)return x-n; return x+n; } inline int num(int x,int k){ if(k==g(a[x]+2))return x; return x+n; } inline void print(int x,int on){ int t; if(!on)t=g(a[x]+2); else t=g(a[x]+1); if(t==0)putchar('A'); else if(t==1)putchar('B'); else putchar('C'); } inline void init(){ cnt=t=l=0; memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); } void solve(){ init(); for(int i=1;i<=m;i++){ int x=p[i].x,l=p[i].l,y=p[i].y,r=p[i].r; if(a[x]==l)continue; int u=num(x,l),v=num(y,r); if(a[y]==r)add(u,f(u)); else{ add(u,v);add(f(v),f(u)); } } for(int i=1;i<=2*n;i++) if(!dfn[i])tarjan(i); for(int i=1;i<=n;i++) if(to[i]==to[i+n])return; for(int i=1;i<=n;i++){ if(to[i]<to[i+n])print(i,0); else print(i,1); } puts("");exit(0); } void dfs(int now){ if(now==d+1){ solve();return; } a[mp[now]]=0;dfs(now+1); a[mp[now]]=1;dfs(now+1); } int main(){ n=read();read(); for(int i=1;i<=n;i++){ a[i]=getc(); if(a[i]==3)mp[++d]=i; } m=read(); for(int i=1;i<=m;i++){ p[i].x=read(),p[i].l=getc(); p[i].y=read(),p[i].r=getc(); } dfs(1); puts("-1"); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +
+++++++++++++++++++++++++++++++++++++++++++