游戏[NOI2017]

链接

loj

题解

3-SAT???

不好意思,那是NP问题。

先不考虑 ‘x’ 的限制。显然每个点有一种情况必定不能选,于是就变成2-SAT了。

于是我们可以 $3^d$ 枚举 x 的每一位必定不选什么,时间复杂度 $O((n+m)3^d)$。

考虑如果存在一个合法方案,那么在是 x 的那一位,你只需要枚举剩下两个的其中一个就好了!

于是直接枚举 x 的每一位是否不选a或b就可以判断是否有满足条件的解了。

时间复杂度 $O((n+m)2^d)$。

tarjan打错两次也是没谁了,看来夜晚是真的不适合我学OI。。。

注意dfs时low[u]=min(low[u],dfn[v])的前提是v还在栈里。

程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <bits/stdc++.h>
using namespace std;
#define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
#define fo(i,j,k) for(int i=(j),end_i=(k);i<=end_i;i++)
#define ff(i,j,k) for(int i=(j),end_i=(k);i< end_i;i++)
#define fd(i,j,k) for(int i=(j),end_i=(k);i>=end_i;i--)
#define DEBUG(x) cerr<<#x<<"="<<x<<endl
#define all(x) (x).begin(),(x).end()
#define cle(x) memset(x,0,sizeof(x))
#define lowbit(x) ((x)&-(x))
#define ll long long
#define ull unsigned ll
#define db double
#define lb long db
#define pb push_back
#define mp make_pair
#define fi first
#define se second
inline int read()
{
int x=0; char ch=getchar(); bool f=0;
for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
return f?-x:x;
}
#define CASET fo(___,1,read())
const int N=100010;
int n,m;
vector<int> adj[N];
int tim,scc_cnt,dfn[N],low[N],st[N],top,bel[N];
bool ins[N];
inline void add(int x,int y) {adj[x].pb(y);}
void dfs(int u)
{
dfn[u]=low[u]=++tim; ins[u]=1; st[++top]=u;
for(auto v:adj[u])
if(!dfn[v])
dfs(v),low[u]=min(low[u],low[v]);
else if(ins[v])
low[u]=min(low[u],dfn[v]);
if(low[u]==dfn[u])
{
++scc_cnt;
do
{
bel[st[top]]=scc_cnt;
ins[st[top]]=0;
}while(st[top--]!=u);

}
}
inline void init()
{
scc_cnt=tim=top=0;
fo(i,1,n+n) adj[i].clear(),dfn[i]=low[i]=bel[i]=ins[i]=0;
}
char s[N];
int x[N],y[N],lx[N],ly[N];
inline int calc(int x,int y)
{
if(s[x]==0) return (y==1)?x:x+n;
else return (y==0)?x:x+n;
}
inline int other(int x)
{
return x>n?x-n:x+n;
}
inline void check()
{
init();
int u,v;
fo(i,1,m)
if(s[x[i]]!=lx[i])
{
u=calc(x[i],lx[i]);
if(s[y[i]]==ly[i])
{
if(u>n) add(u,u-n);
else add(u,u+n);
continue;
}
v=calc(y[i],ly[i]);
add(u,v); add(other(v),other(u));
}
fo(i,1,n+n) if(!dfn[i]) dfs(i);
fo(i,1,n) if(bel[i]==bel[i+n]) return;
fo(i,1,n)
if(bel[i]<bel[i+n])
{
if(s[i]==0) putchar('B');
else putchar('A');
}
else
{
if(s[i]==2) putchar('B');
else putchar('C');
}
exit(0);
}
int id[10],d;
char t[10];
int main()
{
n=read(); read();
scanf("%s",s+1);
fo(i,1,n) if(s[i]=='x') id[d++]=i;
fo(i,1,n) s[i]-='a';
m=read();
fo(i,1,m)
{
x[i]=read(); scanf("%s",t); lx[i]=t[0]-'A';
y[i]=read(); scanf("%s",t); ly[i]=t[0]-'A';
}
int cnt_d=1<<d;
ff(sta,0,cnt_d)
{
ff(i,0,d) s[id[i]]=((sta>>i)&1);
check();
}
puts("-1");
return 0;
}