[NOI2017] 游戏
作者:互联网
- 题意:
- 思路:其实很水就二进制枚举一下x是'A'还是'a'即可
不过做题的时候我u->v(选u就会选v)我没有连v'->u,理论上图是含盖必要逻辑的,但是我们要的是含盖所有逻辑,因为要保持2-SAT图的对称性,这是很多问题的前提。 - code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
char s[N];
int n,nn,dfn[N],low[N],mp[N],Bl[N],SCC,id[N][3],_[N],px[N],tx,nxt[N],to[N],head[N],ecnt,st[N],tp,Time;
bool In_s[N];
void add_edge(int u,int v) {nxt[++ecnt]=head[u];to[ecnt]=v;head[u]=ecnt;}
struct query {int p1,c1,p2,c2;}Q[N];
void Tarjan(int u) {
dfn[u]=low[u]=++Time;In_s[u]=1;st[++tp]=u;
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];
if(!dfn[v]) Tarjan(v),low[u]=min(low[u],low[v]);
else if(In_s[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]) {
SCC++;int v;
do {
v=st[tp--];In_s[v]=0;Bl[v]=SCC;
}while(v!=u);
}
}
bool _rd() {for(int i=1;i<=n;i++)if(Bl[i]==Bl[_[i]])return 0;return 1;}
void Clear() {SCC=tp=Time=ecnt=0;for(int i=1;i<=nn;i++)low[i]=dfn[i]=Bl[i]=head[i]=0;}
void Print() {
for(int i=1;i<=n;i++) {
if(Bl[i]<Bl[_[i]]) printf("%c",'A'+mp[i]);
else printf("%c",'A'+mp[_[i]]);
}
}
int main() {
int d,m;
scanf("%d%d",&n,&d);nn=n<<1;
scanf("%s",s+1);
for(int i=1;i<=n;i++) {
_[i]=i+n;_[i+n]=i;
if(s[i]=='a') {id[i][1]=i;id[i][2]=i+n;}
else if(s[i]=='b') {id[i][0]=i;id[i][2]=i+n;}
else if(s[i]=='c') {id[i][0]=i;id[i][1]=i+n;}
else px[tx++]=i;
for(int k=0;k<3;k++)mp[id[i][k]]=k;
}
scanf("%d",&m);
for(int i=1;i<=m;i++) {char c1[3],c2[3];scanf("%d%s%d%s",&Q[i].p1,c1,&Q[i].p2,c2);Q[i].c1=c1[0]-'A';Q[i].c2=c2[0]-'A';}
for(int t=0;t<(1<<d);t++) {
for(int i=0;i<d;i++) {
int x=px[i];
if((1<<i)&t) {id[x][0]=0;id[x][1]=x,id[x][2]=x+n;}
else {add_edge(x+n,x);id[x][0]=x;id[x][1]=x+n;id[x][2]=0;}
for(int k=0;k<3;k++)mp[id[x][k]]=k;
}
for(int i=1;i<=m;i++) {
int x=id[Q[i].p1][Q[i].c1],y=id[Q[i].p2][Q[i].c2];
if(!x)continue;
if(!y){add_edge(x,_[x]);continue;}
add_edge(x,y);add_edge(_[y],_[x]);
}
for(int i=1;i<=nn;i++) if(!dfn[i])Tarjan(i);
if(!_rd()){Clear();}
else {Print();return 0;}
}
printf("-1");
return 0;
}
标签:NOI2017,nxt,head,游戏,int,ecnt,dfn,low 来源: https://www.cnblogs.com/bestime/p/15920609.html