• [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即可。时间复杂度 (OBig((n+m)2^dBig))

    代码:

    #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
    ",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('
    ');
    	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;
    }
    

  • 相关阅读:
    五、Java对象和类
    四、JavaString字符串
    三、Java语句
    二、Java基本数据类型
    一、Java主类结构
    bat常用命令
    iOS 如何获得app的版本和系统的版本
    英语----时态---将来时态的四种对比
    英语----时态---将来时态的
    英语----时态---现在进行时与过去进行时
  • 原文地址:https://www.cnblogs.com/Troverld/p/14621887.html
Copyright © 2020-2023  润新知