【NOI2017游戏】 枚举+2SAT
%%%2SAT大神love
小 L 计划进行 场游戏,每场游戏使用一张地图,小 L 会选择一辆车在该地图上完成游戏。
小 L 的赛车有三辆,分别用大写字母 、B、C 表示。地图一共有四种,分别用小写字母、a、b、c 表示。
其中,赛车 不适合在地图 a 上使用,赛车 B 不适合在地图 b 上使用,赛车 C 不适合在地图 c 上使用,而地图 则适合所有赛车参加。
适合所有赛车参加的地图并不多见,最多只会有 张。
场游戏的地图可以用一个小写字母组成的字符串描述。例如:S 表示小L计划进行 8 场游戏,其中第 场和第 场的地图类型是 ,适合所有赛车,第 2场和第 场的地图是 ,不适合赛车 ,第 场和第 场的地图是 ,不适合赛车 ,第 场和第 场的地图是 ,不适合赛车 。
小 L 对游戏有一些特殊的要求,这些要求可以用四元组 (i, h_i, j, h_j) 来描述,表示若在第 i 场使用型号为 h_i 的车子,则第 场游戏要使用型号为 h_j 的车子。
你能帮小 L 选择每场游戏使用的赛车吗?如果有多种方案,输出任意一种方案。
如果无解,输出
小 L 计划进行 3 场游戏,其中第 场的地图类型是 x,适合所有赛车,第 场和第 3 场的地图是,不适合赛车 。
小 L 希望:若第 场游戏使用赛车 A,则第 2 场游戏使用赛车 。
那么为这 场游戏分别安排赛车 A、、A 可以满足所有条件。
若依次为 场游戏安排赛车为 BBB 或 BAA时,也可以满足所有条件,也被视为正确答案。
但依次安排赛车为 AAB 或 ABC 时,因为不能满足所有条件,所以不被视为正确答案。
除了万能图就是一个裸的2-sat依赖.考虑万能图也就是直接2^d枚举图是什么就可以了(只用考虑其中两种情况,因为对于剩下情况的已经考虑过了).
这里学到了一个新操作,一般的想法染色找方案都是建立反图之后top-sort一下.但是如果是对偶图,满足所属强连通分量小的在反图拓扑图上的拓扑序越大(优先涂色).那么就判以下就可以了.
-1
。
输入格式
输入第一行包含两个非负整数 ,。
输入第二行为一个字符串 S。
n, d, S 的含义见题目描述,其中 包含 个字符,且其中恰好 d 个为小写字母 x。
输入第三行为一个正整数 ,表示有 m 条用车规则。
接下来 行,每行包含一个四元组 i,h_i,j,h_j ,其中 i,j 为整数,h_i,h_j 为字符 A 、B 或 C,含义见题目描述。
输出格式
输出一行。
若无解输出
-1
。
样例
样例输入
3 1
xcc
1
1 A 2 B
样例输出
ABA
数据范围与提示

#include<stdio.h> #include<iostream> #include<cstdio> using namespace std; const int maxn = 4e5 + 5; int n,d,m; char ss[maxn]; struct node{ int i,j; char hi,hj; }xj[maxn]; int tot; int st[15],tp; int en[maxn],nt[maxn],la[maxn],owo; void adg(int x,int y) { en[++owo] = y; nt[owo] = la[x]; la[x] = owo; } int dfn[maxn] , low[maxn], dfx , blo[maxn],scc; bool inst[maxn]; int sta[maxn],top; int dy[maxn][3]; int ANS[maxn]; void tarjan(int x) { low[x] = dfn[x] = ++dfx; sta[++top] = x; inst[x] = 1; for(int it=la[x];it;it=nt[it]) { int y = en[it]; if(!dfn[y]) { tarjan(y); low[x] = min(low[x],low[y]); } else if(inst[y]) low[x] = min(low[x],dfn[y]); } if(low[x]==dfn[x]) { int y; ++scc; do{ y = sta[top--]; inst[y] = 0; blo[y] = scc; }while(y!=x); } } int XF(int x) { return x>n?x-n:x+n; } bool isok() { owo = dfx = scc = 0; for(int i=1;i<=n;i++) { int zz = 0; for(int j=0;j<3;j++) { if(ss[i]-'A'!=j&&(!zz)) dy[i][j] = i,zz=1; else if(ss[i]-'A'==j) dy[i][j] = -1; else dy[i][j] = i+n; } ANS[i] = 0; } for(int i=1;i<=tot;i++) { la[i] = low[i] = dfn[i] = blo[i] = 0; } for(int i=1;i<=m;i++) { int xx = xj[i].i; char ox = xj[i].hi; int yy = xj[i].j; char oy = xj[i].hj; if(ox==ss[xx]) continue; if(oy==ss[yy]) adg(dy[xx][ox-'A'],XF(dy[xx][ox-'A'])); else { adg(dy[xx][ox-'A'],dy[yy][oy-'A']); adg(XF(dy[yy][oy-'A']),XF(dy[xx][ox-'A'])); } } for(int i=1;i<=tot;i++) { if(!dfn[i]) tarjan(i); } for(int i=1;i<=n;i++) { if(blo[i]==blo[i+n]) return 0; if(blo[i]<blo[i+n]) ANS[i] = 1; else ANS[i] = 2; } for(int i=1;i<=n;i++) { for(int j=0;j<3;j++) { if(dy[i][j]==-1) continue; if(--ANS[i]==0) { putchar(j+'A'); } } } return 1; } void dfs(int now) { if(now==d+1) { if(isok()) exit(0); return; } ss[st[now]] = 'A'; dfs(now+1); ss[st[now]] = 'B'; dfs(now+1); } int main() { scanf("%d%d",&n,&d); d = 0; tot = 2*n; scanf("%s",&ss[1]); for(int i=1;i<=n;i++) { if(ss[i]=='x') st[++d] = i; else ss[i] = ss[i]-'a'+'A'; } scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d %c%d %c",&xj[i].i,&xj[i].hi,&xj[i].j,&xj[i].hj); } dfs(1); puts("-1"); }