[BZOJ4945][Noi2017]游戏 2-sat
对于所有的x,我们枚举他的地图类型,事实上我们只需要枚举前两种地形就可以覆盖所有的情况。
之后就变成了裸的2-sat问题。
对于一个限制,我们分类讨论:
1.h[u]不可选,跳过
2.h[v]不可选,则h[v]也不可选,将u与u‘连边,表示u不可选。
3.否则从u向v连边表示选u就必须选v,从u’向v‘连边表示选v'就必须选u’(逆否命题)。
tarjan缩点判断可行性。
输出方案按照缩点编号选择编号小的点输出即可(逆序拓扑序)。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<cmath> 6 #include<algorithm> 7 #define maxn 400005 8 using namespace std; 9 inline int read() { 10 int x=0,f=1;char ch=getchar(); 11 for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; 12 for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; 13 return x*f; 14 } 15 struct Edge {int to,nxt;}e[maxn*2]; 16 int head[maxn],cnt; 17 void add(int u,int v) {e[cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt++;} 18 struct Ask {int u,v;char a[10],b[10];}q[maxn]; 19 int n,d,pos[maxn],m; 20 char s[maxn],cs[maxn]; 21 bool flag=0; 22 int dfn[maxn],low[maxn],tot,bel[maxn],par[maxn],l[maxn],r[maxn],sta[maxn],top,scc; 23 bool vis[maxn],inq[maxn]; 24 void init() { 25 memset(head,-1,sizeof(head));cnt=0; 26 memset(dfn,0,sizeof(dfn)); 27 memset(low,0,sizeof(low)); 28 memset(bel,0,sizeof(bel));tot=0;scc=0; 29 memset(vis,0,sizeof(vis)); 30 memset(inq,0,sizeof(inq)); 31 } 32 void tarjan(int x) { 33 dfn[x]=low[x]=++tot;sta[++top]=x;inq[x]=1; 34 for(int i=head[x];i>=0;i=e[i].nxt) { 35 int to=e[i].to; 36 if(!dfn[to]) { 37 tarjan(to); 38 low[x]=min(low[x],low[to]); 39 } 40 else if(inq[to]) {low[x]=min(low[x],dfn[to]);} 41 } 42 if(dfn[x]==low[x]) { 43 scc++; 44 while(1) { 45 inq[sta[top]]=0; 46 bel[sta[top--]]=scc; 47 if(sta[top+1]==x) break; 48 } 49 } 50 } 51 int que[maxn],fro,tail,in[maxn]; 52 void work() { 53 init(); 54 for(int i=1;i<=n;i++) { 55 int ttmp=0; 56 if(s[i]=='x') {s[i]=cs[i];ttmp=1;} 57 if(s[i]=='a') {l[i]=i+n,r[i]=i+n+n;} 58 if(s[i]=='b') {l[i]=i,r[i]=i+n+n;} 59 if(s[i]=='c') {l[i]=i,r[i]=i+n;} 60 if(ttmp==1) s[i]='x'; 61 par[l[i]]=r[i];par[r[i]]=l[i];vis[r[i]]=vis[l[i]]=1; 62 } 63 int ql,qr; 64 for(int i=1;i<=m;i++) { 65 if(q[i].a[1]=='A') ql=q[i].u; 66 else if(q[i].a[1]=='B') ql=q[i].u+n; 67 else ql=q[i].u+n+n; 68 if(q[i].b[1]=='A') qr=q[i].v; 69 else if(q[i].b[1]=='B') qr=q[i].v+n; 70 else qr=q[i].v+n+n; 71 if(ql==qr) continue; 72 if(!vis[ql]) continue; 73 if(!vis[qr]) { 74 add(ql,par[ql]); 75 continue; 76 } 77 add(ql,qr);add(par[qr],par[ql]); 78 } 79 for(int i=1;i<=n+n+n;i++) {if(vis[i]&&!dfn[i]) tarjan(i);} 80 for(int i=1;i<=n+n+n;i++) { 81 if(!vis[i]) continue; 82 if(bel[i]==bel[par[i]]) return; 83 } 84 flag=1; 85 for(int i=1;i<=n;i++) { 86 int out=0; 87 if(bel[l[i]]<bel[r[i]]) out=l[i]; 88 else out=r[i]; 89 if(out==i) printf("A"); 90 else if(out==i+n) printf("B"); 91 else printf("C"); 92 } 93 } 94 void dfs(int x) { 95 if(x==d+1) { 96 work(); 97 if(flag) exit(0); 98 return; 99 } 100 cs[pos[x]]='a';dfs(x+1); 101 cs[pos[x]]='b';dfs(x+1); 102 } 103 int main() { 104 n=read(),d=read(); 105 scanf("%s",s+1); 106 for(int i=1;i<=n;i++) {if(s[i]=='x') pos[++pos[0]]=i;} 107 m=read(); 108 for(int i=1;i<=m;i++) {q[i].u=read();scanf("%s",q[i].a+1);q[i].v=read();scanf("%s",q[i].b+1);} 109 dfs(1);printf("-1\n"); 110 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~