zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    html5css练习 旋转
    html5 css练习 画廊 元素旋转
    html5 渐变按钮练习
    html5 旋转导航练习
    html5 javascript 表单练习案例
    html5 p1练习1,移动页面,标准标签布局
    pyqt5desinger的安装即配置
    python 文件操作
    openGL 大作业之n星变换
    openGL 蓝天白云
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793391.html
Copyright © 2011-2022 走看看