zoukankan      html  css  js  c++  java
  • 2-Sat问题

    二分+2-Sat

    判断是否可行

    输出字典序最小的解

    输出字典序可行解

    其实这些都是小问题,最重要的是建图,请看论文。

    特殊的建边方式,如果a b是一对,a必须选,那么就是b->a建边。

    HDU 3062 Party

    模板题

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    #define LL long long
    struct node
    {
        int u,v,next;
    }edge[2001*1001];
    int t,scnt,top;
    int first[2001];
    int DFN[2001];
    int Low[2001];
    int Belong[2001];
    int in[2001],stack[2001];
    void CL()
    {
        t = top = scnt = 0;
        memset(first,-1,sizeof(first));
        memset(DFN,0,sizeof(DFN));
    }
    void add(int u,int v)
    {
        edge[t].u = u;
        edge[t].v = v;
        edge[t].next = first[u];
        first[u] = t ++;
    }
    void Tarjan(int u)
    {
        int v,i;
        DFN[u] = Low[u] = ++ t;
        in[u] = 1;
        stack[top++] = u;
        for(i = first[u];i != -1;i = edge[i].next)
        {
            v = edge[i].v;
            if(!DFN[v])
            {
                Tarjan(v);
                if(Low[u] > Low[v])
                {
                    Low[u] = Low[v];
                }
            }
            else if(in[v] && Low[u] > DFN[v])
            {
                Low[u] = DFN[v];
            }
        }
        if(DFN[u] == Low[u])
        {
            scnt ++;
            do
            {
                v = stack[--top];
                in[v] = 0;
                Belong[v] = scnt;
            }while(u != v);
        }
    }
    int main()
    {
        int n,m,a1,a2,c1,c2,i,u,v;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            CL();
            for(i = 0;i < m;i ++)
            {
                scanf("%d%d%d%d",&a1,&a2,&c1,&c2);
                u = a1*2+c1;
                v = a2*2+c2;
                add(u,v^1);
                add(v,u^1);
            }
            for(i = 0;i < 2*n;i ++)
            {
                if(!DFN[i])
                {
                    Tarjan(i);
                }
            }
            for(i = 0;i < n;i ++)
            {
                if(Belong[2*i] == Belong[2*i+1])
                break;
            }
            if(i == n)
            printf("YES
    ");
            else
            printf("NO
    ");
        }
    
        return 0;
    }
    View Code

    HDU 1814 Peaceful Commission

    论文上的例题,输出字典序。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    #define LL long long
    #define N 8001
    int que[2*N];
    int flag[2*N];
    int first[2*N];
    int t,n,num;
    struct node
    {
        int u,v,next;
    }edge[60001];
    void CL()
    {
        t = 1;
        memset(first,-1,sizeof(first));
        memset(flag,0,sizeof(flag));
    }
    void add(int u,int v)
    {
        edge[t].u = u;
        edge[t].v = v;
        edge[t].next = first[u];
        first[u] = t ++;
    }
    int dfs(int x)
    {
        int i,v;
        if(flag[x] == 1)
        return 1;
        else if(flag[x] == 2)
        return 0;
        flag[x] = 1;
        flag[x^1] = 2;
        que[num++] = x;
        for(i = first[x];i != -1;i = edge[i].next)
        {
            v = edge[i].v;
            if(!dfs(v)) return 0;
        }
        return 1;
    }
    int judge()
    {
        int i,j;
        for(i = 0;i < 2*n;i ++)
        {
            if(flag[i]) continue;
            num = 0;
            if(!dfs(i))
            {
                for(j = 0;j < num;j ++)
                {
                    flag[que[j]] = 0;
                    flag[que[j]^1] = 0;
                }
                if(!dfs(i^1))
                return 0;
            }
        }
        return 1;
    }
    int main()
    {
        int m,u,v,i;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            CL();
            for(i = 0;i < m;i ++)
            {
                scanf("%d%d",&u,&v);
                u --;
                v --;
                add(u,v^1);
                add(v,u^1);
            }
            if(judge())
            {
                for(i = 0;i < 2*n;i ++)
                {
                    if(flag[i] == 1) printf("%d
    ",i+1);
                }
            }
            else
            {
                printf("NIE
    ");
            }
        }
        return 0;
    }
    View Code

    HDU 3648 Wedding

    输出可行解。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <queue>
    #include <algorithm>
    using namespace std;
    #define LL long long
    struct node
    {
        int u,v,next;
    }edge[100001],g[100001];
    int t,scnt,top,T;
    int first[2001];
    int DFN[2001];
    int op[2001];
    int Low[2001];
    int Belong[2001];
    int in[2001],stack[2001];
    int input[2001];
    int flag[2001];
    void CL()
    {
        T = t = top = scnt = 0;
        memset(first,-1,sizeof(first));
        memset(DFN,0,sizeof(DFN));
        memset(flag,0,sizeof(flag));
    }
    void add(int u,int v)
    {
        edge[t].u = u;
        edge[t].v = v;
        edge[t].next = first[u];
        first[u] = t ++;
    }
    void _add(int u,int v)
    {
        g[T].u = u;
        g[T].v = v;
        g[T].next = first[u];
        first[u] = T ++;
    }
    void Tarjan(int u)
    {
        int v,i;
        DFN[u] = Low[u] = ++ t;
        in[u] = 1;
        stack[top++] = u;
        for(i = first[u];i != -1;i = edge[i].next)
        {
            v = edge[i].v;
            if(!DFN[v])
            {
                Tarjan(v);
                if(Low[u] > Low[v])
                {
                    Low[u] = Low[v];
                }
            }
            else if(in[v] && Low[u] > DFN[v])
            {
                Low[u] = DFN[v];
            }
        }
        if(DFN[u] == Low[u])
        {
            scnt ++;
            do
            {
                v = stack[--top];
                in[v] = 0;
                Belong[v] = scnt;
            }while(u != v);
        }
    }
    void tpsort()
    {
         queue<int> que;
         memset(first,-1,sizeof(first));
         int i,v,u;
         for(i = 0;i < t;i ++)
         {
             u = Belong[edge[i].u];
             v = Belong[edge[i].v];
             if(u != v)
             {
                 _add(v,u);
                 input[u] ++;
             }
         }
         for(i = 1;i <= scnt;i ++)
         {
             if(input[i] == 0) que.push(i);
         }
         while(!que.empty())
         {
             u = que.front();
             que.pop();
             if(flag[u] == 0)
             {
                 flag[u] = 1;
                 flag[op[u]] = 2;
             }
             for(i = first[u];i != -1;i = g[i].next)
             {
                 v = g[i].v;
                 if(--input[v] == 0) que.push(v);
             }
         }
    
    }
    int main()
    {
        int n,m,i,u,v;
        char s1,s2;
        while(scanf("%d%d%*c",&n,&m)!=EOF)
        {
            if(n == 0&&m == 0) break;
            CL();
            for(i = 0;i < m;i ++)
            {
                scanf("%d%c%*c%d%c%*c",&u,&s1,&v,&s2);
                if(s1 == 'w') u = u*2;
                else u = u*2 + 1;
                if(s2 == 'w') v = v*2;
                else v = v*2 + 1;
                if(u != (v^1))
                {
                    add(u,v^1);
                    add(v,u^1);
                }
            }
            add(0,1);
            for(i = 0;i < 2*n;i ++)
            {
                if(!DFN[i])
                {
                    Tarjan(i);
                }
            }
            for(i = 0;i < n;i ++)
            {
                if(Belong[2*i] == Belong[2*i+1])
                break;
                op[Belong[2*i]] = Belong[2*i+1];
                op[Belong[2*i+1]] = Belong[2*i];
            }
            if(i != n)
            {
                printf("bad luck
    ");
                continue;
            }
            tpsort();
            int z = 0;
            for(i = 0; i < 2*n; i++)
            {
                 if(flag[Belong[i]] == 1 && i != 1)
                 {
                    if(z) printf(" ");
                    z = 1;
                    printf("%d", i/2);
                    if(i%2 == 0)
                    printf("h");
                    else
                    printf("w");
                }
             }
             printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    luogu2568GCD题解--欧拉函数
    POJ1845Sumdiv题解--约数之和
    luogu1731生日蛋糕题解--恶心剪枝
    luogu1156垃圾陷阱题解--背包DP
    CF336C-Vasily the Bear and Sequence题解--贪心
    luogu2261余数求和题解--整除分块
    UVA10140PrimeDistance题解--质数/技巧
    CSP2019 游记
    CSP-SJX2019 和积和
    NOIP2018 游记
  • 原文地址:https://www.cnblogs.com/naix-x/p/3967984.html
Copyright © 2011-2022 走看看