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\n");

        else

        printf("NO\n");

    }



    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\n",i+1);

            }

        }

        else

        {

            printf("NIE\n");

        }

    }

    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\n");

            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("\n");

    }

    return 0;

}
View Code

 

你可能感兴趣的:(问题)