zoukankan      html  css  js  c++  java
  • 洛谷3825 [NOI2017]游戏 2-sat

    原文链接http://www.cnblogs.com/zhouzhendong/p/8146041.html


    题目传送门 - 洛谷3825


    题解

      我们考虑到地图中x的个数很少,最多只有8个。

      所以我们可以考虑穷举。

      我们只需要把x变成a和b,这样就涵盖了选择A,B,C的三种情况。

      所以我们状压枚举每一个x可以变成什么情况。

      然后对于每一种情况,几乎就是2-sat裸题了。

      然后我们考虑特殊情况:

      如果选了A就得选择B。

      如果A的状态不合法,那么显然这条边是不用建立的。

      否则:

        如果B的状态不合法,那么显然不可以到达A,于是我们将状态A连向他的对立点。

        如果B的状态合法,那么我们要连接2条边。一条是A到B的,一条是opp(B)到opp(A)的。(其中opp(x)表示状态x的对立状态)

      同学们注意了,Tarjan缩点千万别写错,我已经连续3个程序死在Tarjan缩点上面了。


    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstdlib>
    using namespace std;
    const int N=500005*2,M=1000005*2;
    struct Gragh{
    	int cnt,x[M],y[M],nxt[M],fst[N];
    	void clear(){
    		cnt=0;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b){
    		x[++cnt]=a,y[cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g,g2;
    int n,m,d,pos[10],w[N][3];
    int dfn[N],low[N],vis[N],inst[N],st[N],bh[N],top,time,cnt;
    int o[N],in[N],q[N],res[N],head,tail;
    char place[N];
    struct Limit{
    	int i,j,hi,hj;
    }l[M];
    void Get_Pos(){
    	int cnt=0;
    	for (int i=1;i<=n;i++)
    		if (place[i]=='x')
    			pos[++cnt]=i;
    }
    int opp(int x){
    	return x+n*(x<=n?1:-1);
    }
    void Tarjan_Prepare(){
    	top=time=cnt=0;
    	memset(st,0,sizeof st);
    	memset(bh,0,sizeof bh);
    	memset(dfn,0,sizeof dfn);
    	memset(low,0,sizeof low);
    	memset(vis,0,sizeof vis);
    	memset(inst,0,sizeof inst);
    }
    void Tarjan(int x){
    	dfn[x]=low[x]=++time;
    	st[++top]=x;
    	inst[x]=vis[x]=1;
    	for (int i=g.fst[x];i;i=g.nxt[i])
    		if (!vis[g.y[i]]){
    			Tarjan(g.y[i]);
    			low[x]=min(low[x],low[g.y[i]]);
    		}
    		else if (inst[g.y[i]])
    			low[x]=min(low[x],low[g.y[i]]);
    	if (dfn[x]==low[x]){
    		cnt++;
    		bh[st[top]]=cnt;
    		inst[st[top]]=0;
    		while (st[top--]!=x){
    			bh[st[top]]=cnt;
    			inst[st[top]]=0;
    		}
    	}
    }
    bool check(){
    	for (int i=1;i<=n;i++)
    		if (bh[i]==bh[i+n])
    			return 0;
    		else
    			o[bh[i]]=bh[i+n],o[bh[i+n]]=bh[i];
    	return 1;
    }
    void solve(int s){
    	for (int i=1;i<=d;i++)
    		place[pos[i]]='a'+((s>>(i-1))&1);
    	for (int i=1;i<=n;i++){
    		if (place[i]=='a')w[i][0]=0,w[i][1]=i,w[i][2]=i+n;
    		if (place[i]=='b')w[i][0]=i,w[i][1]=0,w[i][2]=i+n;
    		if (place[i]=='c')w[i][0]=i,w[i][1]=i+n,w[i][2]=0;
    	}
    	g.clear();
    	for (int I=1;I<=m;I++){
    		int i=l[I].i,j=l[I].j,hi=l[I].hi,hj=l[I].hj;
    		if (!w[i][hi])
    			continue;
    		if (w[j][hj]){
    			g.add(w[i][hi],w[j][hj]);
    			g.add(opp(w[j][hj]),opp(w[i][hi]));
    		}
    		else
    			g.add(w[i][hi],opp(w[i][hi]));
    	}
    	Tarjan_Prepare();
    	for (int i=1;i<=n*2;i++)
    		if (!vis[i])
    			Tarjan(i);
    	if (!check())
    		return;
    	memset(in,0,sizeof in);
    	g2.clear();
    	for (int i=1;i<=g.cnt;i++)
    		if (bh[g.x[i]]!=bh[g.y[i]])
    			g2.add(bh[g.y[i]],bh[g.x[i]]),in[bh[g.x[i]]]++;
    	head=tail=0;
    	for (int i=1;i<=cnt;i++)
    		if (!in[i])
    			q[++tail]=i;
    	memset(res,0,sizeof res);
    	while (head<tail){
    		int x=q[++head];
    		if (!res[x])
    			res[x]=1,res[o[x]]=-1;
    		for (int i=g2.fst[x];i;i=g2.nxt[i]){
    			in[g2.y[i]]--;
    			if (!in[g2.y[i]])
    				q[++tail]=g2.y[i];
    		}
    	}
    	for (int i=1;i<=n;i++){
    		int v=res[bh[i]]==1?i:(i+n),c;
    		for (int j=0;j<3;j++)
    			if (w[i][j]==v)
    				c=j;
    		printf("%c",c+'A');
    	}
    	exit(0);
    }
    int main(){
    	scanf("%d%d%s%d",&n,&d,place+1,&m);
    	for (int i=1;i<=m;i++){
    		char ch1[3],ch2[3];
    		scanf("%d%s%d%s",&l[i].i,ch1,&l[i].j,ch2);
    		l[i].hi=ch1[0]-'A',l[i].hj=ch2[0]-'A';
    	}
    	Get_Pos();
    	for (int i=0;i<(1<<d);i++)
    		solve(i);
    	printf("-1");
    	return 0;
    }
    

      

  • 相关阅读:
    js继承《转》
    千分位分割正则
    所有事件失效
    658. Find K Closest Elements
    278. First Bad Version
    153. Find Minimum in Rotated Sorted Array
    11. Container With Most Water
    205. Isomorphic Strings
    75. Sort Colors
    695. Max Area of Island
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/LuoguP3825.html
Copyright © 2011-2022 走看看