• [NOI2017]游戏


    这题可能是(NOI2017)里面最简单的一道题目了吧(目测比蔬菜简单到不知道哪里去了)

    考虑看到这种约束条件想(2-SAT),发现我们可以令(u)表示(u)这个点能选的第一个点,(u')表示能选的第二个点。

    那么显然有下面的连边:

    1. 如果(u​)的赛道不能够选这个摩的,显然忽略这个限制
    2. (u​)的赛道能选这个,(v​)不能选它对应的,那么显然这个限制条件一旦(u​)选了这个,那么就GG了。所以连边((u,u')​)
    3. 除此之外,连接((u,v)),((v',u'))

    然后直接跑(2-SAT)就行了。

    什么?你问我怎么考虑(x)?暴力枚举即可。(只要枚举('a','b')两种情况,因为如果是(c),显然只有((a,c))((b,c))两种可能,然后之前选(a)(b)的时候都考虑了,所以不要算(C)

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<iostream>
    using namespace std;
    #define re register
    #define ll long long
    inline int gi(){
        int f=1,sum=0;char ch=getchar();
        while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
        return f*sum;
    }
    const int N=100010;
    int n,d,m,a[N];char s[N];
    struct ques{int u,h1,v,h2;}q[N];
    struct node{int to,nxt;}e[N<<1];
    int front[N],cnt;
    void Add(int u,int v){e[++cnt]=(node){v,front[u]};front[u]=cnt;}
    int dfn[N],Time,low[N],in[N],sta[N],top,scc,bl[N];
    void Tarjan(int u){
        dfn[u]=low[u]=++Time;in[u]=1;sta[++top]=u;
        for(int i=front[u];i;i=e[i].nxt){
            int v=e[i].to;
            if(!dfn[v]){
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(in[v])low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u]){
            int v;scc++;
            do{
                v=sta[top--];bl[v]=scc;in[v]=0;
            }while(v!=u);
        }
    }
    int getid(int u,int col){
        if(a[u]==col)return 0;
        if(!a[u])return u*2+col-1;
        if(a[u]==1)return u*2+col/2;
        return u*2+col;
    }
    void solve(){
        memset(front,0,sizeof(front));cnt=0;Time=0;memset(dfn,0,sizeof(dfn));
        for(int i=1;i<=m;i++){
            int x=getid(q[i].u,q[i].h1),y=getid(q[i].v,q[i].h2);
            if(x)
                if(y)Add(x,y),Add(y^1,x^1);
                else Add(x,x^1);
        }
        for(int i=2;i<=2*n+1;i++)
            if(!dfn[i])Tarjan(i);
        for(int i=1;i<=n;i++)
            if(bl[i*2]==bl[i*2^1])return;
        for(int i=1;i<=n;i++){
            if(!a[i])printf("%c",bl[i*2]<bl[i*2^1]?'B':'C');
            else if(a[i]==1)printf("%c",bl[i*2]<bl[i*2^1]?'A':'C');
            else printf("%c",bl[i*2]<bl[i*2^1]?'A':'B');
        }
        puts("");
        exit(0);
    }
    void dfs(int now){
        if(now>n){solve();return;}
        if(a[now]==-1){a[now]=0;dfs(now+1);a[now]=1;}
        dfs(now+1);
    }
    char aaa[5],bbb[5];
    int main(){
        n=gi();d=gi();
        for(int i=1;i<=n;i++){
            char ch=getchar();int f=0;
            while(ch!='a' && ch!='b' && ch!='c' && ch!='x')ch=getchar();
            if(ch=='x')f=-1;
            else f=ch-'a';
            a[i]=f;
        }
        m=gi();
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%s%d%s",&u,aaa,&v,bbb);
            q[i]=(ques){u,aaa[0]-'A',v,bbb[0]-'A'};
        }
        dfs(1);
        puts("-1");
        return 0;
    }
    
  • 相关阅读:
    [PY3]——logging
    [PY3]——对iterator的处理(解析式、map、reduce、filter)
    php基础语法(文件加载和错误)
    php基础语法(控制语句、数组、函数)
    php基础语法(数据类型、运算符)
    php基础语法(变量)
    java基础语法
    ztree 获取根节点
    每天一个linux命令
    浅谈Web自适应
  • 原文地址:https://www.cnblogs.com/mleautomaton/p/11167600.html
Copyright © 2020-2023  润新知