BZOJ 4945 UOJ #317 NOI2017 游戏 2-SAT 拓扑排序
https://www.lydsy.com/JudgeOnline/problem.php?id=4945
我现在的程序uoj的额外数据通过不了,bzoj应该是原版数据所以可以过??
x不超过8个所以2^8枚举一下就可以了。每个可以选择的状态实际上只有两个所以还是2-SAT。
2-SAT的图需要满足对偶性,所以逆否连边很有用。
我之前不会这种问题怎么输出方案,输出方案的方法就是tarjan之后topsort,再对每个强连通分量决定选还是不选(把矛盾的都不选,和矛盾相反的选,具体看代码里的dfs1函数)。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<iostream> 6 using namespace std; 7 #define LL long long 8 const int maxn=300010; 9 int n,d,fla=0,m; 10 char ch[maxn],ch1[2],ch2[2],ans[maxn]; 11 int pos[10]={}; 12 struct node{ 13 int id1,x,id2,y; 14 }a[maxn]; 15 struct nod{ 16 int y,next; 17 };nod e[maxn],e1[maxn]; 18 int head[maxn]={},head1[maxn]={},tot=0,tot1=0; 19 int low[maxn]={},dfn[maxn]={},sta[maxn]={},bel[maxn]={},cnt=0,tai=0,tly=0; 20 int de[maxn]={},op[maxn]={}; bool vis[maxn]={}; 21 int ob[maxn]={},dd[maxn]={},co[maxn]={}; 22 int q[maxn]={},s=0,t=0; 23 inline void init(int x,int y){ 24 e[++tot].y=y;e[tot].next=head[x];head[x]=tot; 25 } 26 inline void init1(int x,int y){ 27 e1[++tot1].y=y;e1[tot1].next=head1[x];head1[x]=tot1; 28 } 29 void tarjan(int x){ 30 sta[++tai]=x;low[x]=dfn[x]=++cnt;vis[x]=1; 31 for(int i=head[x];i;i=e[i].next){ 32 if(!dfn[e[i].y]){ 33 tarjan(e[i].y); 34 low[x]=min(low[x],low[e[i].y]); 35 } 36 else if(vis[e[i].y]) low[x]=min(low[x],dfn[e[i].y]); 37 } 38 if(low[x]==dfn[x]){ 39 int w;tly++; 40 do{ 41 w=sta[tai--]; 42 bel[w]=tly;vis[w]=0; 43 }while(w!=x); 44 } 45 } 46 void Check(){ 47 memset(dfn,0,sizeof(dfn)); 48 memset(head,0,sizeof(head)); 49 tot=0;cnt=0;tly=0; 50 int aa,bb,cc; 51 for(int i=1;i<=n;i++){ 52 aa=(ch[i]-'a')*n+i;bb=(aa+n-1)%(3*n)+1;cc=(bb+n-1)%(3*n)+1; 53 de[aa]=1;de[bb]=0;de[cc]=0; 54 op[bb]=cc;op[cc]=bb; 55 } 56 for(int i=1;i<=m;i++){ 57 aa=a[i].x*n+a[i].id1;bb=a[i].y*n+a[i].id2; 58 if(aa==bb||de[aa])continue; 59 if(a[i].id1==a[i].id2||de[bb]){ 60 init(aa,op[aa]);//aa一定到op[aa]即表明aa不能选 61 } 62 else{init(op[bb],op[aa]);init(aa,bb);}//图要对偶所以aa连bb逆否也连一下 63 } 64 for(int i=1;i<=3*n;i++){ 65 if(de[i]||dfn[i])continue; 66 tarjan(i); 67 } 68 for(int i=1;i<=3*n;i++){ 69 if(de[i])continue; 70 if(bel[i]==bel[op[i]])return; 71 ob[bel[i]]=bel[op[i]];ob[bel[op[i]]]=bel[i]; 72 } 73 fla=1; 74 } 75 void dfs(int x){ 76 if(x==d+1){ 77 Check();return; 78 } 79 ch[pos[x]]='a';dfs(x+1); 80 if(fla)return; 81 ch[pos[x]]='b';dfs(x+1); 82 } 83 void dfs1(int x){ 84 if(co[x]!=-1)return; 85 co[x]=0;co[ob[x]]=1; 86 for(int i=head1[x];i;i=e1[i].next)dfs1(e1[i].y); 87 } 88 int main(){ 89 scanf("%d%d%s%d",&n,&d,ch+1,&m); 90 for(int i=1;i<=n;i++)if(ch[i]=='x')pos[++pos[0]]=i; 91 for(int i=1;i<=m;i++){ 92 scanf("%d%s%d%s",&a[i].id1,ch1,&a[i].id2,ch2); 93 a[i].x=ch1[0]-'A';a[i].y=ch2[0]-'A'; 94 } 95 dfs(1); 96 if(!fla){ 97 printf("-1\n");return 0; 98 } 99 memset(co,-1,sizeof(co)); 100 for(int i=1;i<=3*n;i++){//强连通分量缩点后拓扑序 101 if(de[i])continue; 102 for(int j=head[i];j;j=e[j].next) 103 if(bel[e[j].y]!=bel[i]){init1(bel[e[j].y],bel[i]);++dd[bel[i]];} 104 } 105 for(int i=1;i<=tly;i++)if(!dd[i])q[++t]=i; 106 while(s<t){ 107 int x=q[++s]; 108 for(int i=head1[x];i;i=e1[i].next){ 109 --dd[e1[i].y]; 110 if(!dd[e1[i].y])q[++t]=e1[i].y; 111 } 112 if(co[x]!=-1)continue; 113 dfs1(ob[x]); 114 } 115 for(int i=1;i<=3*n;i++){if((!de[i])&&co[bel[i]]==1)ans[(i-1)%n]='A'+(i-1)/n;} 116 printf("%s",ans); 117 return 0; 118 }