洛谷 P3825 [NOI2017]游戏 【2-SAT+状压】
2018-03-19 14:35
405 查看
UOJ和洛谷上能A,bzoj 8ms即WA,现在也不是知道为啥……因为我太弱了
先看数据范围发现d非常小,自然想到了状压。
所以先假装都是只能跑两种车的,这显然就是个2-SAT问题了:对于x场没有hx的,直接跳过;对于y场没有hy的,连(x,x'),表示x不能选;对于都有的,连接(x,y),表示选了x必须选y,(y',x'),表示不选y的话也不能选x。
注意!
1 连(x,x')的时候不要直接add(i,i+n)!这里方便起见写成(x,x'),实际上应该是(x,不是x的另一个)
2 (x,y)(y',x')是反着的!后边一条不能连成(x',y')!选了x'并不是一定要选y',但是选y'就意味着不能选x相当于必须选x'!
然后tarjan缩点判每一对点所在的scc编号是否一样,是则无解,否则输出方案:
正常的输出方案应该是输出一对点中拓扑序在前的,其实就相当于在一对点里选一个scc编号小的即可
然后考虑x,就是在最外面套一层二进制枚举x的状态。为什么不是三进制呢?会TLE,因为发现组合并不重要,重要的是每个可选地都在两个一对的方案里出现过即可,也就是只需要枚举x是选(A,C),或者选(B,C)。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=100005; int n,m,d,h ,cnt,a ,p[10],tot,x ,hx ,y ,hy ,id [4],con,top,s ,dfn ,low ,dft,bl ; char c ; bool v ; struct qwe { int ne,to; }e[N*10]; int read() { int r=0,f=1; char p=getchar(); while(p>'9'||p<'0') { if(p=='-') f=-1; p=getchar(); } while(p>='0'&&p<='9') { r=r*10+p-48; p=getchar(); } return r*f; } int readc() { char p=getchar(); while(p<'A'||p>'Z') p=getchar(); return p-'A'+1; } void add(int u,int v) {//cout<<u<<" "<<v<<endl; cnt++; e[cnt].ne=h[u]; e[cnt].to=v; h[u]=cnt; } void tarjan(int u) { low[u]=dfn[u]=++dft; v[s[++top]=u]=1; for(int i=h[u];i;i=e[i].ne) { if(!dfn[e[i].to]) { tarjan(e[i].to); low[u]=min(low[u],low[e[i].to]); } else if(v[e[i].to]) low[u]=min(low[u],dfn[e[i].to]); } if(dfn[u]==low[u]) { con++; while(s[top]!=u) { bl[s[top]]=con; v[s[top--]]=0; } bl[s[top]]=con; v[s[top--]]=0; } } int main() { n=read(),d=read(); scanf("%s",c+1); for(int i=1;i<=n;i++) { if(c[i]=='x') p[++tot]=i; a[i]=c[i]-'a'+1; if(a[i]==1) id[i][2]=0,id[i][3]=1; else if(a[i]==2) id[i][1]=0,id[i][3]=1; else id[i][1]=0,id[i][2]=1; } m=read(); for(int i=1;i<=m;i++) x[i]=read(),hx[i]=readc(),y[i]=read(),hy[i]=readc(); for(int b=0;b<(1<<d);b++) {//cout<<endl; memset(h,0,sizeof(h)); memset(v,0,sizeof(v)); memset(dfn,0,sizeof(dfn)); cnt=0;top=0,con=0;dft=0; int q=b; for(int i=1;i<=tot;i++,q>>=1) { if(q&1) a[p[i]]=1; else a[p[i]]=2; if(a[p[i]]==1) id[p[i]][2]=0,id[p[i]][3]=1; else if(a[p[i]]==2) id[p[i]][1]=0,id[p[i]][3]=1; } // for(int i=1;i<=n;i++) // printf("%d ",a[i]); // cout<<endl; for(int i=1;i<=m;i++) if(a[x[i]]!=hx[i]&&!(x[i]==y[i]&&hx[i]==hy[i])) { if(a[y[i]]==hy[i]) add(x[i]+n*id[x[i]][hx[i]],x[i]+n*(id[x[i]][hx[i]]^1)); else add(x[i]+n*id[x[i]][hx[i]],y[i]+n*id[y[i]][hy[i]]),add(y[i]+n*(id[y[i]][hy[i]]^1),x[i]+n*(id[x[i]][hx[i]]^1)); } for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i); bool f=1; for(int i=1;i<=n;i++) if(bl[i]==bl[i+n]) { f=0; break; } if(f) { for(int i=1;i<=n;i++) { if(bl[i]<bl[i+n]) { if(a[i]==1) printf("B"); else printf("A"); } else { if(a[i]==3) printf("B"); else printf("C"); } } return 0; } } puts("-1"); return 0; }
相关文章推荐
- 洛谷P3825 [NOI2017]游戏
- 洛谷 P3825 游戏[NOI 2017] (2-SAT)
- BZOJ4945 & 洛谷3825 & UOJ317:[NOI2017]游戏——题解
- bzoj4549 LOJ2305 NOI2017 游戏 2-sat
- [BZOJ4945][NOI2017]游戏(2-SAT)
- [2-SAT]NOI2017 .day2 T1 游戏
- 【NOI2017】游戏(搜索,2-sat)
- NOI2017 [NOI2017]游戏 【2-sat】
- 【NOI2017】游戏(搜索,2-sat)
- [2-SAT] [Noi2017]游戏
- 【uoj#317】[NOI2017]游戏 2-SAT
- 【BZOJ4945】[Noi2017]游戏 2-SAT
- [BZOJ4945][NOI2017]游戏(2-SAT)
- 【DFS+2-SAT验证】LibreOJ2305(NOI2017)[游戏]题解
- [BZOJ4549][NOI2017]游戏(2-SAT)
- LOJ_2305_「NOI2017」游戏 _2-sat
- 洛谷 P1005 矩阵取数游戏
- 洛谷P1427 小鱼的数字游戏
- 洛谷1043 数字游戏
- 洛谷 P1005 矩阵取数游戏