BZOJ 4945 [Noi2017]游戏

题解:

这题怎么也卡常数(自己常数大)

对于是x的位置令x='a'或'c' ('b')

然后用2sat验证即可

问题:缩点版的2sat还不会,貌似效率高

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100009;

int n,m,lim;
int limt[maxn][3];
char limc[maxn][3];

int cntp=0;
int xp[maxn];

char ss[maxn];
int cntedge=0;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	head[x]=cntedge;
}

int fla[maxn];
int mark[maxn];
char FS(int x){
	if(ss[x]=='a')return 'b';
	else return 'a';
}
char SE(int x){
	if(ss[x]=='a')return 'c';
	if(ss[x]=='b')return 'c';
	if(ss[x]=='c')return 'b';
}

void Addlims(int i){
	int t1=limt[i][1];
	int t2=limt[i][2];
	char c1=limc[i][1];
	char c2=limc[i][2];
	
	if((t1==t2)&&(c1==c2))return;
	if(c1==ss[t1])return;
	if(c2==ss[t2]){
		if(c1==FS(t1))fla[t1*2+1]=1;
		else fla[t1*2]=1;
		return;
	}
	int x,y;
	if(c1==FS(t1))x=t1*2;
	else x=t1*2+1;
	if(c2==FS(t2))y=t2*2;
	else y=t2*2+1;
	Addedge(x,y);
	Addedge(y^1,x^1);
}

int Sta[maxn],top;
int Dfs(int x){
	if(mark[x^1])return 0;
	if(mark[x])return 1;
	mark[x]=1;
	Sta[++top]=x;
	
	for(int i=head[x];i;i=nex[i]){
		if(!Dfs(to[i]))return 0;
	}
	return 1;
}

int Sol(){
	cntedge=0;
	memset(fla,0,sizeof(fla));
	memset(head,0,sizeof(head));
	memset(mark,0,sizeof(mark));
	for(int i=1;i<=lim;++i)Addlims(i);
//	for(int i=2;i<=n*2+1;++i)cout<<fla[i]<<' ';
//	cout<<endl;
	for(int i=2;i<=n*2+1;i+=2){
		if((!fla[i])&&(!fla[i+1]))continue;
		if(fla[i]&&fla[i+1])return 0;
		if(fla[i]==1){
			if(!Dfs(i))return 0;
		}else{
			if(!Dfs(i+1))return 0;
		}
	}
//	for(int i=2;i<=n*2+1;++i)cout<<mark[i]<<' ';
//	cout<<endl;
	for(int i=2;i<=n*2+1;i+=2){
		if((!mark[i])&&(!mark[i+1])){
			top=0;
			if(!Dfs(i)){
				while(top){
					mark[Sta[top]]=0;--top;
				}
				if(!Dfs(i+1))return 0;
			}
		}
	}
	for(int i=1;i<=n;++i){
		if(mark[i*2]){
			printf("%c",FS(i)-'a'+'A');
		}else{
			printf("%c",SE(i)-'a'+'A');
		}
	}
	return 1;
}

int main(){
//	freopen("game.in","r",stdin);
//	freopen("game.out","w",stdout);
	
	scanf("%d%d",&n,&m);
	scanf("%s",ss+1);
	for(int i=1;i<=n;++i)if(ss[i]=='x')xp[++cntp]=i;
	scanf("%d",&lim);
	for(int i=1;i<=lim;++i){
		scanf("%d",&limt[i][1]);
		limc[i][1]=getchar();
		while(limc[i][1]!='A'&&limc[i][1]!='B'&&limc[i][1]!='C')limc[i][1]=getchar();
		limc[i][1]=limc[i][1]-'A'+'a';
		scanf("%d",&limt[i][2]);
		limc[i][2]=getchar();
		while(limc[i][2]!='A'&&limc[i][2]!='B'&&limc[i][2]!='C')limc[i][2]=getchar();
		limc[i][2]=limc[i][2]-'A'+'a';
	}
	for(int s=0;s<(1<<m);++s){
		for(int i=1;i<=m;++i){
			if(s&(1<<(i-1))){
				ss[xp[i]]='c';
			}else{
				ss[xp[i]]='a';
			}
		}
		if(Sol())return 0;
	}
	cout<<-1<<endl;
	return 0;
}

  

posted @ 2018-03-13 19:35  ws_zzy  阅读(261)  评论(0编辑  收藏  举报