P3825 [NOI2017]游戏

题目

P3825 [NOI2017]游戏

做法

\(x\)地图外的地图好做,模型:\((x,y)\)必须同时选\(x \rightarrow y,y^\prime \rightarrow x^\prime\)

难点在处理\(x\)地图上,三进制枚举车,状压一下也能做,理论时间复杂度\(O(3^d 4m)\),卡不满优化一下也能过吧

往更深层考虑??不枚举选哪个了,枚举选地图,其实只用考虑\(A,B\)就行,\(C\)包含在里面了(反正也只要选一辆)

时间复杂度\(O(2^d 4m)\)

My complete code

#include<bits/stdc++.h>
#include<stack>
using namespace std;
typedef int LL;
const LL maxn=1e6;
struct node{
	LL to,next;
}dis[maxn];
stack<LL> sta;
LL num,n,m,k,tim,tot,d;
LL head[maxn],Scc[maxn],low[maxn],dfn[maxn],pos[maxn],x[maxn],y[maxn],visit[maxn];
char s[maxn],p1[maxn],p2[maxn];
inline void Add(LL u,LL v){
	dis[++num]=(node){v,head[u]},head[u]=num;
}
void Tarjan(LL u){
	visit[u]=1; sta.push(u); low[u]=dfn[u]=++tim;
	for(LL i=head[u];i;i=dis[i].next){
		LL v(dis[i].to);
		if(!dfn[v]){
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}else if(visit[v]) low[u]=min(low[u],low[v]);
	}
	if(low[u]==dfn[u]){
		LL now;
		++tot;
		do{
			now=sta.top(); sta.pop();
			Scc[now]=tot;
			visit[now]=0;
		}while(now!=u);
	}
}
inline bool Check(){
	for(LL i=1;i<=2*n;++i)
	    if(!dfn[i]) Tarjan(i);
	for(LL i=1;i<=n;++i)
	    if(Scc[i]==Scc[i+n]) return false;
	for(LL i=1;i<=n;++i){
		if(Scc[i]<Scc[i+n]){
			if(s[i]=='A') printf("B");
			else printf("A");
		}else{
			if(s[i]=='C') printf("B");
			else printf("C");
		}
	}return true;
}
inline void First(){
	for(LL i=1;i<=2*n;++i) visit[i]=0;
	for(LL i=1;i<=2*n;++i) low[i]=0;
	for(LL i=1;i<=2*n;++i) dfn[i]=0;
	for(LL i=1;i<=2*n;++i) Scc[i]=0;
	for(LL i=1;i<=2*n;++i) head[i]=0;
	while(sta.size()) sta.pop();
	num=tim=tot=0;
}
inline void Solve(){
	LL up((1<<d)-1),x1,x2,y1,y2;
	for(LL i=0;i<=up;++i){
		First();
		for(LL j=1;j<=d;++j)
		    if(((i>>(j-1))&1)==0) s[pos[j]]='A';
		    else s[pos[j]]='B';
		for(LL j=1;j<=m;++j){
			if(p1[j]==s[x[j]]) continue;
			if(p2[j]==s[y[j]]){
				if(p1[j]=='C' || (p1[j]=='B' && s[x[j]]=='C'))
				    Add(x[j]+n, x[j]);
				else
				    Add(x[j], x[j]+n);
				continue;
			}
			if(p1[j]=='A' || (p1[j]=='B'&&s[x[j]]=='A')) x1=x[j],x2=x[j]+n;
			else x1=x[j]+n,x2=x[j];
			if(p2[j]=='A' || (p2[j]=='B'&&s[y[j]]=='A')) y1=y[j],y2=y[j]+n;
			else y1=y[j]+n,y2=y[j];
			
			Add(x1,y1);
			Add(y2,x2);
		}
		if(Check()) return;
	}
	printf("-1");
}
int main(){
	scanf("%d%d",&n,&d);
	scanf(" %s",s+1);
	LL cnt(0);
	for(LL i=1;i<=n;++i)
	    if(s[i]=='x')
	        pos[++cnt]=i;
	    else
	        s[i]='A'+(s[i]-'a');
	scanf("%d",&m);
	for(LL i=1;i<=m;++i){
	    scanf("%d",x+i);
	    scanf(" %c",&p1[i]);
	    scanf("%d",y+i);
	    scanf(" %c",&p2[i]);
	}
	Solve();
	return 0;
}
posted @ 2019-02-03 19:02  y2823774827y  阅读(217)  评论(0编辑  收藏  举报