[NOI2017]游戏

看到那个“特殊的要求”就知道这题是2sat了,只有$8$个x所以不妨枚举每个x分别是什么,直接做要$O\left(3^d\right)$,很明显会T,经过毒瘤yww指点,我们可以随机$200$次左右来硬点这些x,然后就过了23333

对每场游戏设三个布尔变量分别表示开哪种车,对于每场不能用某种车的限制我们把另外两个布尔变量设为2sat中的相反变量即可,对于特殊要求直接连边即可,注意考虑特殊情况和去掉没用的限制

小技巧:2sat输出方案直接比较一个变量和它的相反变量所在强联通分量编号即可,因为强联通分量编号小的点一定在反图拓扑序的前面

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#define NUM(x) ('0'<=x&&x<='9')
char c[2000000];
int ns=0;
inline int rd(){
	while(!NUM(c[ns]))ns++;
	int x=c[ns]-'0';
	for(ns++;NUM(c[ns]);ns++)x=(x<<3)+(x<<1)+c[ns]-'0';
	return x;
}
#define CHR(x) (('a'<=x&&x<='c')||('A'<=x&&x<='C')||x=='x')
inline void str(char*s){
	char*p=s;
	while(!CHR(c[ns]))ns++;
	while(CHR(c[ns]))*(p++)=c[ns++];
}
inline int min(int a,int b){return a<b?a:b;}
int h[150010],nex[200010],to[200010],dfn[150010],low[150010],st[150010],col[150010],M,tp,C;
bool ins[150010];
void add(int a,int b){
	M++;
	to[M]=b;
	nex[M]=h[a];
	h[a]=M;
}
void dfs(int x){
	int i;
	M++;
	dfn[x]=low[x]=M;
	tp++;
	st[tp]=x;
	ins[x]=1;
	for(i=h[x];i;i=nex[i]){
		if(dfn[to[i]]==0){
			dfs(to[i]);
			low[x]=min(low[x],low[to[i]]);
		}else if(ins[to[i]])
			low[x]=min(low[x],dfn[to[i]]);
	}
	if(dfn[x]==low[x]){
		C++;
		do{
			i=st[tp];
			tp--;
			ins[i]=0;
			col[i]=C;
		}while(i!=x);
	}
}
int n,m,r[150010],x[100010],y[100010];
char s[50010],sa[100010],sb[100010];
bool solve(){
	int i;
	M=0;
	memset(h,0,sizeof(h));
	memset(dfn,0,sizeof(dfn));
	memset(low,0,sizeof(low));
	memset(col,0,sizeof(col));
	for(i=1;i<=n;i++){
		r[i]=r[i+n]=r[i+n*2]=0;
		if(s[i]==0){
			r[i+n]=i+2*n;
			r[i+2*n]=i+n;
		}else if(s[i]==1){
			r[i]=i+2*n;
			r[i+2*n]=i;
		}else{
			r[i]=i+n;
			r[i+n]=i;
		}
	}
	for(i=1;i<=m;i++){
		if(x[i]==y[i]&&sa[i]==sb[i])continue;
		if(s[x[i]]==sa[i])continue;
		if(s[y[i]]==sb[i]){
			add(x[i]+sa[i]*n,r[x[i]+sa[i]*n]);
			continue;
		}
		add(x[i]+sa[i]*n,y[i]+sb[i]*n);
		add(r[y[i]+sb[i]*n],r[x[i]+sa[i]*n]);
	}
	C=0;
	for(i=1;i<=3*n;i++){
		if(dfn[i]==0){
			M=0;
			dfs(i);
		}
	}
	for(i=1;i<=3*n;i++){
		if(r[i]&&col[i]==col[r[i]])return 0;
	}
	for(i=1;i<=n;i++){
		if(s[i]==0)putchar(col[i+n]<col[i+2*n]?'B':'C');
		if(s[i]==1)putchar(col[i]<col[i+2*n]?'A':'C');
		if(s[i]==2)putchar(col[i]<col[i+n]?'A':'B');
	}
	return 1;
}
int d,pos[10];
int main(){
	srand(time(0));
	c[fread(c,1,2000000,stdin)]=0;
	int i,j;
	char a[5],b[5];
	n=rd();
	d=rd();
	str(s+1);
	m=rd();
	d=0;
	for(i=1;i<=n;i++){
		if(s[i]=='x'){
			d++;
			pos[d]=i;
		}else
			s[i]-='a';
	}
	for(i=1;i<=m;i++){
		x[i]=rd();
		str(a);
		y[i]=rd();
		str(b);
		sa[i]=a[0]-'A';
		sb[i]=b[0]-'A';
	}
	for(j=0;j<200;j++){
		for(i=1;i<=d;i++)s[pos[i]]=rand()%3;
		if(solve())return 0;
	}
	puts("-1");
}

猜你喜欢

转载自www.cnblogs.com/jefflyy/p/9090621.html