zoukankan      html  css  js  c++  java
  • [NOI2017]游戏(2-SAT)

    [NOI2017]游戏(2-SAT)

    bzoj4945 luoguP3825

    题目描述参照luogu

    题解:

    乍一看三辆车,你以为我是$3-SAT$,其实还是我$2-SAT$哒!

    能放三辆车的只有至多$8$条,似乎暴力枚举所有状态都行...?

    我们发现$3^8$有点太大了。。。

    但我们考虑一下

    x赛道可以放三种车,但我们将它改成随便两种赛道就可以让三辆车都能在上面放

    之后剩下的裸跑2-SAT就完事

    加边?

    对于限制$x选p则y选q$

    分类讨论:

    x不能放p:不加边

    x能放p但y不能放q:(x,p)连(x,另一种车)

    其他的:(x,p)连(y,q),(y,另一种)连(x,另一种)

    完结,时间复杂度$O(2^{d}*n)$

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N=100069;
    template<typename TP>inline void read(TP &_t)
    {
        TP _r=0,_f=1;char _c=getchar();
        while(_c<'0'||_c>'9'){if(_c=='-')_f=-1;_c=getchar();}
        while(_c>='0'&&_c<='9'){_r=_r*10+_c-'0';_c=getchar();}
        _t=_r*_f;
    }
    inline void gc(int &_t)
    {
        char _c=getchar();
        while(_c<'A'||_c>'C') _c=getchar();
        _t=_c;
    }
    struct ban{int x,p,y,q;ban(){}ban(int x,int p,int y,int q):x(x),p(p),y(y),q(q){}}b[N];
    int n,d;
    char trackstr[N];
    int track[N];
    int xpos[10],xc;
    int m;
    
    
    struct sumireko{int to,ne;}e[N<<2];
    int he[N],ecnt;
    void addline(int f,int t)
    {
        e[++ecnt].to=t;
        e[ecnt].ne=he[f];
        he[f]=ecnt;
    }
    
    int bl[N],ba;
    int dep[N],low[N],da;
    int sta[N],stp;
    bool ins[N];
    void tj(int x)
    {
        dep[x]=low[x]=++da;
        sta[++stp]=x,ins[x]=1;
        for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)
        {
            if(!dep[t]) tj(t),low[x]=min(low[x],low[t]);
            else if(ins[t]) low[x]=min(low[x],dep[t]);
        }
        if(dep[x]==low[x])
        {
            ba++;
            int px=0;
            while(px!=x)
            {
                px=sta[stp--];
                bl[px]=ba,ins[px]=0;
            }
        }
    }
    
    bool check()
    {
        for(int i=1;i<=n;i++) if(bl[i]==bl[i+n]) return 0;
        return 1;
    }
    inline int pt(int x,int p)
    {
        switch(track[x])
        {
            case 0:{return p==1?x:x+n;break;}
            default:{return p==0?x:x+n;break;}
        }
    }
    inline int op(int x,int p)
    {
        switch(track[x])
        {
            case 0:{return p==1?x+n:x;break;}
            default:{return p==0?x+n:x;break;}
        }
    }
    void memclr()
    {
        memset(bl,0,sizeof(bl));
        memset(dep,0,sizeof(dep));
        memset(low,0,sizeof(low));
        memset(he,0,sizeof(he));
        ecnt=ba=da=stp=0;
    }
    
    int xi,yi,pi,qi;
    int main()
    {
        read(n),read(d);
        scanf("%s",trackstr+1);
        for(int i=1;i<=n;i++) switch(trackstr[i])
        {
            case 'x':{xpos[++xc]=i;break;}
            default:{track[i]=trackstr[i]-'a';break;}
        }
        read(m);
        for(int i=1;i<=m;i++)
        {
            read(xi),gc(pi),read(yi),gc(qi);
            b[i]=ban(xi,pi-'A',yi,qi-'A');
        }
        for(int s=0;s<(1<<d);s++)
        {
            memclr();
            for(int i=1;i<=d;i++) track[xpos[i]]=((s>>(i-1))&1);
            for(int i=1;i<=m;i++)
            {
                int x=b[i].x,p=b[i].p,y=b[i].y,q=b[i].q;
                if(track[x]==p) continue;
                if(track[y]==q) addline(pt(x,p),op(x,p));
                else addline(pt(x,p),pt(y,q)),addline(op(y,q),op(x,p));
            }
            for(int i=1;i<=n*2;i++)
                if(!dep[i]) tj(i);
            if(check())
            {
                for(int i=1;i<=n;i++)
                    if(bl[i]<bl[i+n]) putchar(track[i]==0?'B':'A');
                    else putchar(track[i]==2?'B':'C');
                return 0;
            }
        }
        printf("-1");
        return 0;
    }
    View Code
  • 相关阅读:
    自制 os 极简教程1:写一个操作系统有多难
    面试官问我redis数据类型,我回答了8种
    全网最硬核讲解计算机启动流程
    cinder-volume Required RPC API Old
    Docker swarm 容器流量追踪
    postgres schema访问权限设置
    骑士cms < 6.0.48任意文件包含漏洞简记
    Socket学习
    网络编程
    交换机和路由器的区别
  • 原文地址:https://www.cnblogs.com/rikurika/p/11490519.html
Copyright © 2011-2022 走看看