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

    这是约半年前写的题解了,就搬过来吧

    感觉这是NOI2017最水的一题(当然我还是不会2333),因为是一道裸的2-SAT。我就是看着这道题学的2-SAT

    算法一:暴力枚举。对于abc二进制枚举,对于x则采用三进制枚举即可,复杂度O(3^d*2^(n-d)),再进行适当剪支,期望得分:40~50

    算法二:对于d=0的点,采用2-SAT算法,这是最裸的2-SAT,这样,复杂度为O(n+m),综合算法一,期望得分为60

    算法三:不妨对于d个x,采用三进制枚举,枚举a/b/c,再做裸的2-SAT即可,复杂度O(3^d*(n+m)),期望得分:75~90,如果常数小可以X过去

    算法四:不难发现,三进制枚举不但效率慢,而且难写、没必要,对于判断会很复杂,不如只枚举禁止使用A/B,因为这样已经包含了A/B/C三种赛车,所以可以这么做(因为题目只要求一组解),复杂度O(2^d*(n+m)),期望得分:100

    难点:2-SAT和输出方案的2-SAT

    注意:选A就选B等价于选B'就选A’,所以需要连接双向边!!

    不说了上code

    #include<bits/stdc++.h>
    #define mem(x) memset(x,0,sizeof x)
    using namespace std;
    const int N=2e5+99;
    int n,m,d,scc,cnt,top,c[N],s1[N],t1[N],dfn[N],low[N],part[N],hd[N],v[N],nxt[N],q[N];
    char s[N],s2[N],t2[N],t[N];
    bool vis[N],flag;
    void add(int x,int y){v[++cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt;}
    int opp(int x){return x>n?x-n:x+n;}
    int jisuan(int x,char ch)
    {
        if(s[x]=='a')return ch=='B'?x:x+n;
        if(s[x]=='b'||s[x]=='c')return ch=='A'?x:x+n;
        if(ch=='C')return x+n;
        return x;
    }
    void tarjan(int u)
    {
        dfn[u]=low[u]=++cnt;
        q[++top]=u;
        vis[u]=1;
        for(int i=hd[u];i;i=nxt[i])
        if(!dfn[v[i]])
        {
            tarjan(v[i]);
            low[u]=min(low[u],low[v[i]]);
        }
        else if(vis[v[i]])low[u]=min(low[u],dfn[v[i]]);
        if(dfn[u]==low[u])
        {
            part[u]=++scc;
            vis[u]=0;
            int now;
            do{
                now=q[top--];
                vis[now]=0;
                part[now]=scc;
            }while(now!=u);
        }
    }
    void solve()
    {
        scc=cnt=0;
        mem(dfn);mem(low);mem(part);mem(hd);mem(nxt);
        for(int i=1;i<=m;i++)
        if(s[s1[i]]!='x'&&s[t1[i]]!='x'&&s[s1[i]]-32!=s2[i])
        {
            int u=jisuan(s1[i],s2[i]),v;
            if(s[t1[i]]-32==t2[i])add(u,opp(u));
            else{
                v=jisuan(t1[i],t2[i]);
                add(u,v);add(opp(v),opp(u));
            }
        }
        else{
            char S=s[s1[i]],T=s[t1[i]];
            int x=c[s1[i]],y=c[t1[i]];
            if(S=='x'&&T=='x'&&s2[i]!=t[x])
            {
                int u=jisuan(s1[i],s2[i]),v;
                if(t2[i]==t[y])add(u,opp(u));
                else{
                    v=jisuan(t1[i],t2[i]);
                    add(u,v);add(opp(v),opp(u));
                }
            }
            else if(S=='x'&&T!='x'&&s2[i]!=t[x])
            {
                int u=jisuan(s1[i],s2[i]),v;
                if(s[t1[i]]-32==t2[i])add(u,opp(u));
                else{
                    v=jisuan(t1[i],t2[i]);
                    add(u,v);add(opp(v),opp(u));
                }
            }
            else if(S!='x'&&T=='x'&&s[s1[i]]-32!=s2[i])
            {
                int u=jisuan(s1[i],s2[i]),v;
                if(t2[i]==t[y])add(u,opp(u));
                else{
                    v=jisuan(t1[i],t2[i]);
                    add(u,v);add(opp(v),opp(u));
                }
            }
        }
        cnt=0;
        for(int i=1;i<=n*2;i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=n;i++)if(part[i]==part[i+n])return;
        for(int i=1;i<=n;i++)
        if(part[i]<part[i+n])
        {
            if(s[i]=='a')printf("B");
            else if(s[i]=='b'||s[i]=='c')printf("A");
            else if(t[c[i]]=='A')printf("B");
            else printf("A");
        }
        else{
            if(s[i]=='a'||s[i]=='b')printf("C");
            else if(s[i]=='c')printf("B");
            else if(t[c[i]]=='A')printf("C");
            else printf("B");
        }
        flag=1;
    }
    void fact(int k)
    {
        if(flag)return;
        if(k>d){solve();return;}
        t[k]='A';fact(k+1);t[k]='B';fact(k+1);
    }
    int main()
    {
        scanf("%d%d",&n,&d);
        d=0;
        scanf("%s",s+1);
        for(int i=1;i<=n;i++)if(s[i]=='x')c[i]=++d;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)scanf("%d %c%d %c",&s1[i],&s2[i],&t1[i],&t2[i]);
        fact(1);
        if(!flag)puts("-1");
    }
    View Code
  • 相关阅读:
    [转载]HashSet的存储机制
    Java基础加强
    [转载]JDK的动态代理深入解析(Proxy,InvocationHandler)
    Java语言基础Html
    Java语言基础JavaScript
    多线程数据与控制同步
    Expression Tree Basics表达式树基础
    调试优化利器ASP.NET 跟踪
    css position relative ,absolute ,float
    .net date /日期格式化
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10155788.html
Copyright © 2011-2022 走看看