• 【BZOJ4945】游戏(NOI2017)-2-SAT+枚举


    测试地址:游戏
    做法:本题需要用到2-SAT+枚举。
    看到大部分的地图都只能用两种赛车,赛车之间有一些依赖关系,这显然就是个2-SAT。而对于极少数的能用三种赛车的地图,我们枚举这些地图是不用A还是不用B,这样可以保证不漏掉方案,对每种情况做2-SAT即可,这样我们就解决了这一题,时间复杂度为O(2dn)
    注意一个比较重要的处理是,建图时如果一条限制指向的点不能使用,就表示指向它的那个点也不能使用,而一个点不能取的限制体现在图里就是从这个点向同组的另一个点连边。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,d,X0[100010],Y0[100010],cnt=0,pos[10],tim,st[100010],top;
    int dfn[100010],low[100010],first[200010],q[200010],tot;
    int belong[100010],totscc,col[200010],in[200010]={0},Q[200010],QQ[200010];
    char s[50010],X1[100010],Y1[100010];
    bool vis[200010],inst[200010];
    struct edge
    {
        int v,next;
    }e[2000010];
    
    void insert(int a,int b)
    {
        e[++tot].v=b;
        e[tot].next=first[a];
        first[a]=tot;
    }
    
    void tarjan(int v)
    {
        vis[v]=inst[v]=1;
        dfn[v]=low[v]=++tim;
        st[++top]=v;
        int now=top;
        for(int i=first[v];i;i=e[i].next)
        {
            if (!vis[e[i].v])
            {
                tarjan(e[i].v);
                low[v]=min(low[v],low[e[i].v]);
            }
            else if (inst[e[i].v]) low[v]=min(low[v],dfn[e[i].v]);
        }
        if (low[v]==dfn[v])
        {
            totscc++;
            for(int i=top;i>=now;i--)
            {
                belong[st[i]]=totscc;
                inst[st[i]]=0;
            }
            top=now-1;
        }
    }
    
    bool check()
    {
        for(int i=1;i<=n;i++)
            if (belong[i]==belong[n+i]) return 1;
        return 0;
    }
    
    void color(int x)
    {
        int h=1,t=1;
        QQ[1]=x;
        while(h<=t)
        {
            int v=QQ[h++];
            if (vis[v]) continue;
            vis[v]=1;
            col[v]=0;
            for(int i=first[v];i;i=e[i].next)
                QQ[++t]=e[i].v;
        }
    }
    
    void solve()
    {
        for(int i=1;i<=n;i++)
        {
            q[belong[i]]=belong[n+i];
            q[belong[n+i]]=belong[i];
        }
        for(int i=1;i<=(n<<1);i++)
        {
            for(int j=first[i];j;j=e[j].next)
                if (belong[i]!=belong[e[j].v])
                {
                    insert(belong[e[j].v],belong[i]);
                    in[belong[i]]++;
                }
        }
        int h=1,t=0;
        for(int i=(n<<1)+1;i<=totscc;i++)
            if (!in[i]) Q[++t]=i;
        while(h<=t)
        {
            int v=Q[h++];
            if (vis[v]) continue;
            vis[v]=1;
            col[v]=1;
            color(q[v]);
            for(int i=first[v];i;i=e[i].next)
            {
                in[e[i].v]--;
                if (!in[e[i].v]) Q[++t]=e[i].v;
            }
        }
        for(int i=1;i<=n;i++)
        {
            if (s[i]=='a') printf("%c",col[belong[i]]?'B':'C');
            if (s[i]=='b') printf("%c",col[belong[i]]?'A':'C');
            if (s[i]=='c') printf("%c",col[belong[i]]?'A':'B');
        }
    }
    
    int point(int x,char y)
    {
        if (s[x]!='c') return y=='C';
        else return y=='B';
    }
    
    bool work()
    {
        memset(first,0,sizeof(first));
        tot=0;
        for(int i=1;i<=m;i++)
        {
            if (s[X0[i]]==X1[i]-'A'+'a') continue;
            int px=point(X0[i],X1[i]);
            if (s[Y0[i]]==Y1[i]-'A'+'a')
            {
                insert(X0[i]+px*n,X0[i]+(!px)*n);
                continue;
            }
            int py=point(Y0[i],Y1[i]);
            insert(X0[i]+px*n,Y0[i]+py*n);
            insert(Y0[i]+(!py)*n,X0[i]+(!px)*n);
        }
    
        memset(vis,0,sizeof(vis));
        tim=top=0;
        totscc=n<<1;
        for(int i=1;i<=(n<<1);i++)
            if (!vis[i]) tarjan(i);
        if (check()) return 0;
        solve();
        return 1;
    }
    
    int main()
    {
        scanf("%d%d",&n,&d);
        scanf("%s",s+1);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
            scanf("%d %c%d %c",&X0[i],&X1[i],&Y0[i],&Y1[i]);
    
        bool flag=0;
        for(int i=1;i<=n;i++)
            if (s[i]=='x') pos[cnt++]=i;
        for(int i=0;i<(1<<d);i++)
        {
            for(int j=0;j<d;j++)
                s[pos[j]]=(i&(1<<j))?'a':'b';
            if (work()) {flag=1;break;}
        }
        if (!flag) printf("-1");
    
        return 0;
    }
  • 相关阅读:
    数据库周刊33丨腾讯Tbase新版本发布;“2020数据技术嘉年华”有奖话题遴选;阿里云技术面试题;APEX 实现数据库自动巡检;MYSQL OCP题库……
    常用ASCII码对照表
    linux 环境root用户新建用户和删除用户
    Utl_Raw.Cast_To_Raw(dbms_obfuscation_toolkit.md5())
    months_between()
    GREATEST(),ROUND(),
    TRUNC()
    oracle+function
    oracle存储过程----遍历游标的方法(for、fetch、while)
    oracle+seqTest
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793391.html
Copyright © 2020-2023  润新知