2-SAT的题啦
考虑到x很小,我们只需要暴力枚举x是什么就好了,然后每个点就两种状态,2-SAT模型啦!
总的复杂度
O(3d∗n)
然后呢,建图的时候,将一些边建好,剩下的与x有关的到时候再建,可以减少很多复杂度。。要不可能会超。。但是uoj的数据一般般,不这么做也行,然后bzoj根本就没有spj
然后我这个写法不是哪里出了一点点小问题,uoj95分,还有一个点WA了。。看了半天,很绝望。。
我又不想写spj,于是对拍也不大好。。就这样吧,估计也就是一点点细节问题。。
就这样吧,但我觉得方法是没有问题啊,大家可以借鉴哈!但抄代码就别了。。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=50005*2;
const int M=100005*2;
int n,d,m;
char ss[N];
struct qq
{
int i,hi;
int j,hj;
}s[M];
int read ()
{
char ch=getchar();int x=0;
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x;
}
int read1 ()
{
char ch=getchar();
while (ch!='A'&&ch!='B'&&ch!='C') ch=getchar();
return ch-'A'+1;
}
struct qy
{
int x,y,last;
}e[M];int num,last[N];
void init (int x,int y)
{
num++;
e[num].x=x;e[num].y=y;
e[num].last=last[x];
last[x]=num;
}
int a[N];
int P (int x,int y)//在x这个地方填y的编号
{
if (a[x]==y) return -1;
int cnt=0;
for (int u=1;u<=3;u++)
{
if (a[x]==u) continue;
if (u==y) break;
cnt++;
}
return cnt*n+x;
}
bool tf=false;
int dfn[N],low[N],belong[N],cnt,sta[N],lalal,shen;
bool in[N];
int mymin (int x,int y){return x<y?x:y;}
void dfss (int x)
{
dfn[x]=low[x]=++lalal;
sta[++cnt]=x;
in[x]=true;
for (int u=last[x];u!=-1;u=e[u].last)
{
int y=e[u].y;
if (dfn[y]==-1)
{
dfss(y);
low[x]=mymin(low[x],low[y]);
}
else if (in[y]) low[x]=mymin(dfn[y],low[x]);
}
if (low[x]==dfn[x])
{
shen++;
int now;
do
{
now=sta[cnt--];
belong[now]=shen;
in[now]=false;
}while (now!=x);
}
}
qy e1[M];int num1,last1[N];
int du[N];
void init1 (int x,int y)
{
du[y]++;
num1++;
e1[num1].x=x;e1[num1].y=y;
e1[num1].last=last1[x];
last1[x]=num1;
}
void rebt ()
{
num1=0;memset(last1,-1,sizeof(last1));
for (int u=1;u<=2*n;u++)
for (int i=last[u];i!=-1;i=e[i].last)
{
int y=e[i].y;
if (belong[u]!=belong[y])
init1(belong[y],belong[u]);
}
}
int op[N];
int col[N];
void dfs1 (int x)
{
if (col[x]!=0) return ;
col[x]=2;
for (int u=last1[x];u!=-1;u=e1[u].last)
{
int y=e1[u].y;
dfs1(y);
}
}
void topsort ()
{
queue<int> q;
for (int u=1;u<=shen;u++)
if (du[u]==0) q.push(u);
while (!q.empty())
{
int x=q.front();q.pop();
//printf("%d",x);
if (col[x]!=0) continue;
col[x]=1;dfs1(op[x]);
for (int u=last1[x];u!=-1;u=e1[u].last)
{
int y=e1[u].y;
du[y]--;
if (du[y]==0) q.push(y);
}
}
}
void print (int x,int y)
{
//printf("%d %d %d\n",x,y,a[x]);
int cnt=0;
for (int u=1;u<=3;u++)
{
if (a[x]==u) continue;
cnt++;
if (cnt==y)
{
printf("%c",u+'A'-1);
break;
}
}
}
void check ()//当前这个序列有没有一个合法方案
{
num=0;memset(last,-1,sizeof(last));
for (int u=1;u<=m;u++)
{
int x=P(s[u].i,s[u].hi),y=P(s[u].j,s[u].hj);
if (x==-1) continue;
if (y==-1) init(x,(x+n)%(2*n));
else {init(x,y);init((y+n)%(2*n),(x+n)%(2*n));}
}
memset(dfn,-1,sizeof(dfn));
memset(in,false,sizeof(in));
shen=lalal=cnt=0;
for (int u=1;u<=2*n;u++)
if (dfn[u]==-1)
dfss(u);
for (int u=1;u<=n;u++)
if (belong[u]==belong[u+n])
return ;
/* printf("%d %d\n",a[1],a[2]);
for (int u=1;u<=m;u++)
{
int x=P(s[u].i,s[u].hi),y=P(s[u].j,s[u].hj);
// if (x==-1) continue;
printf("YES:%d %d\n",x,y);
/*if (y==-1) init(x,(x+n)%(2*n));
init(x,y);
}*/
// for (int u=1;u<=num;u++) printf("%d %d\n",e[u].x,e[u].y);
tf=true;
memset(du,0,sizeof(du));
rebt();
for (int u=1;u<=n;u++)
{
op[belong[u]]= belong[u+n];
op[belong[u+n]]=belong[u];
}
memset(col,0,sizeof(col));
/*for (int u=1;u<=2*n;u++) printf("%d ",[u]);
printf("\n");
for (int u=1;u<=num1;u++) printf("%d %d\n",e1[u].x,e1[u].y);*/
topsort();
// for (int u=1;u<=2*n;u++) printf("%d ",col[u]);
for (int u=1;u<=n;u++)
if (col[belong[u]]==1) print(u,1);
else print(u,2);
}
void dfs (int x)//到哪一位了
{
if (tf) return ;
if (x>n) {check();return ;}
if (ss[x]=='x')
{
a[x]=1;dfs(x+1);
a[x]=2;dfs(x+1);
a[x]=3;dfs(x+1);
}
else
{
a[x]=ss[x]-'a'+1;
dfs(x+1);
}
}
int main()
{
scanf("%d%d",&n,&d);
scanf("%s",ss+1);
scanf("%d",&m);
for (int u=1;u<=m;u++)
{
s[u].i=read();s[u].hi=read1();
s[u].j=read();s[u].hj=read1();
}
dfs(1);
if (tf==false) printf("-1");
/* if (tf) printf("YES\n");
else printf("NO\n");*/
return 0;
}