https://www.luogu.com.cn/problem/P3825
(NOI也不过如此,盲目自信.jpg
这题我们知道对于地图a,b,c来说,只有两种选择,那么就是2-sat裸题了,
考虑地图x,由于d<=8,我们让它要么是A,B要么是B,C,就包含所有情况了,只需要2^d的枚举
之前建图忘记对称建了,WA了一发,身败名裂.jpg
对称建也就是对于i要选择j,这个命题等于 选择 opp(j) 要选择 opp(i)
。
#include<bits/stdc++.h>
using namespace std;
const int maxl=1e5+10;
int n,d,m,ind,top,ff;
int dfn[maxl],low[maxl],f[maxl],s[maxl];
int a[maxl][2],h[maxl][5];
char ch[maxl],tmp[3],out[maxl];
bool ansflag;
bool in[maxl],ans[maxl];
vector <int> xx,e[maxl];
inline void prework()
{
scanf("%d%d",&n,&d);
scanf("%s",ch+1);
for(int i=1;i<=n;i++)
{
if(ch[i]=='x')
xx.push_back(i);
if(ch[i]=='a')
a[i][0]=2,a[i][1]=3;
if(ch[i]=='b')
a[i][0]=1,a[i][1]=3;
if(ch[i]=='c')
a[i][0]=1,a[i][1]=2;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&h[i][1]);
scanf("%s",ch);h[i][2]=ch[0]-'A'+1;
scanf("%d",&h[i][3]);
scanf("%s",ch);h[i][4]=ch[0]-'A'+1;
}
}
inline void tarjan(int u)
{
dfn[u]=low[u]=++ind;
in[u]=true;s[++top]=u;
for(auto v : e[u])
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(in[v])
low[u]=min(low[u],dfn[v]);
if(dfn[u]==low[u])
{
ff++;int v;
do
{
v=s[top--];
f[v]=ff;in[v]=false;
}while(u!=v);
}
}
inline bool solv()
{
ff=0;ind=0;top=0;
for(int i=1;i<=2*n;i++)
{
dfn[i]=low[i]=f[i]=0;
e[i].clear();in[i]=true;
}
int u,v;
for(int i=1;i<=m;i++)
{
u=h[i][1];v=h[i][3];
for(int j=0;j<=1;j++)
if(h[i][2]==a[u][j])
{
if(h[i][4]!=a[v][0] && h[i][4]!=a[v][1])
e[u+j*n].push_back(u+(1-j)*n);
else if(h[i][4]==a[v][0])
{
e[u+j*n].push_back(v);
e[v+n].push_back(u+(1-j)*n);
}
else
{
e[u+j*n].push_back(v+n);
e[v].push_back(u+(1-j)*n);
}
}
}
for(int i=1;i<=2*n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
if(f[i]==f[i+n])
return false;
for(int i=1;i<=n;i++)
ans[i]=f[i]>f[i+n];
return true;
}
inline void dfs(int k)
{
if(k==d)
{
if(solv())
{
ansflag=true;
for(int i=1;i<=n;i++)
out[i]=a[i][ans[i]]+'A'-1;
}
return;
}
a[xx[k]][0]=1;a[xx[k]][1]=2;
dfs(k+1);
if(ansflag)
return;
a[xx[k]][0]=2;a[xx[k]][1]=3;
dfs(k+1);
}
inline void mainwork()
{
ansflag=false;
dfs(0);
}
inline void print()
{
if(!ansflag)
printf("-1");
else
for(int i=1;i<=n;i++)
printf("%c",out[i]);
}
int main()
{
prework();
mainwork();
print();
return 0;
}