[NOI2017] 游戏

X.[NOI2017] 游戏

因为并没有专门开2SAT笔记,所以就放这了

好久没用2SAT了,都忘光了……

首先,我们可以 \(2^d\) 枚举所有 x 型赛道是当 a 型用还是当 b 型用,因为 a 型允许你选 BC,而 b 型又允许你选 A,这样就涵盖了全部情形。

这样之后,我们便考虑建立2SAT模型。

对于一组限制 \((u,v)\),若 \(u\) 选择的颜色是被禁止的颜色,显然可以不予考虑;若 \(v\) 选择的颜色是被禁止的颜色,显然这会使得选 \(u\) 不合法;怎么让选 \(u\) 不合法呢?连边 \((u,u')\) 即可。

否则,其就是一条常规的限制,连边 \((u,v)\),同时也别忘记连边 \((v',u')\),因为若 \(v\) 没有选择强制它选择的颜色,则 \(u\) 也一定不能选择具有强制效力的颜色。

于是直接Tarjan跑2SAT即可。时间复杂度 \(O\Big((n+m)2^d\Big)\)

代码:

#include<bits/stdc++.h>
using namespace std;
int a[3][3]={{-1,0,1},{0,-1,1},{0,1,-1}},b[3][2]={{1,2},{0,2},{0,1}};
int n,d,m,tp[50010];
char str[50010];
struct EDGE{
	int u,v,cu,cv;
	EDGE(){}
	EDGE(int U,int V,int CU,int CV){u=U,v=V,cu=CU,cv=CV;}
}e[100100];
vector<int>v[100010],u;
int dfn[100010],low[100010],tot,col[100010],c;
stack<int>s;
void Tarjan(int x){
	dfn[x]=low[x]=++tot,s.push(x);
	for(auto y:v[x]){
		if(!dfn[y])Tarjan(y),low[x]=min(low[x],low[y]);
		else if(!col[y])low[x]=min(low[x],dfn[y]); 
	}
	if(dfn[x]>low[x])return;
	c++;
	while(s.top()!=x)col[s.top()]=c,s.pop();
	col[s.top()]=c,s.pop();
}
bool che(){
	tot=c=0;for(int i=1;i<=2*n;i++)dfn[i]=low[i]=col[i]=0,v[i].clear();
	for(int i=1;i<=m;i++){
		int X=a[tp[e[i].u]][e[i].cu],Y=a[tp[e[i].v]][e[i].cv];
//		printf("%d %d\n",X,Y);
		if(e[i].cu==tp[e[i].u])continue;
		if(e[i].cv==tp[e[i].v])v[X*n+e[i].u].push_back((!X)*n+e[i].u);else v[X*n+e[i].u].push_back(Y*n+e[i].v),v[(!Y)*n+e[i].v].push_back((!X)*n+e[i].u);
	}
	for(int i=1;i<=2*n;i++)if(!dfn[i])Tarjan(i);
	for(int i=1;i<=n;i++)if(col[i]==col[i+n])return false;
	for(int i=1;i<=n;i++)putchar('A'+b[tp[i]][(col[i]>col[i+n])]);putchar('\n');
	return true;
}
int main(){
	scanf("%d%d",&n,&d);
	scanf("%s",str+1);
	for(int i=1;i<=n;i++)if(str[i]=='x')u.push_back(i);else tp[i]=str[i]-'a';
	scanf("%d",&m);
	for(int i=1,x,y;i<=m;i++)scanf("%d%s%d%s",&x,str,&y,str+10),e[i]=EDGE(x,y,str[0]-'A',str[10]-'A');
	for(int i=0;i<(1<<u.size());i++){
		for(int j=0;j<u.size();j++)tp[u[j]]=(i>>j)&1;
		if(che())return 0;
	}
	puts("-1");
	return 0;
}

posted @ 2021-04-06 14:50  Troverld  阅读(53)  评论(0编辑  收藏  举报