HDU 1814 Peaceful Commission[2_SAT]

2—sat建图总结
1.元素关系有以下11种

A[x]
NOT A[x]
A[x] AND A[y]
A[x] AND NOT A[y]
A[x] OR A[y]
A[x] OR NOT A[y]
NOT (A[x] AND A[y])
NOT (A[x] OR A[y])
A[x] XOR A[y]
NOT (A[x] XOR A[y])
A[x] XOR NOT A[y] 

And 结果为1:建边 ~x->y, ~y->x (两个数都为1)

And 结果为0:建边 y->~x , x->~y(两个数至少有一个为0)

OR  结果为1:建边 ~x->y , ~y->x(两个数至少有一个为1)

OR  结果为0:建边 x->~x , y->~y(两个数都为0)

XOR 结果为1:建边 x->~y , ~x->y , ~y->x , y -> ~x (两个数一个为0,一个为1)

XOR 结果为0:建边 x->y , ~x->~y , y->x ~y->~x(两个数同为1或者同为0)

 

题意:找出字典序最小的解

分析:直接暴力枚举DFS,首先将所有的点都置为为染色,然后我们从第一个点开始DFS染色,我们先尝试将i染

           成红色(答案中的颜色),将~i染成蓝色,然后dfs i的所有后继并染色,如果对于后继j没有染色,那么将j然

           后为红色,~j染成蓝色。如果后继j已经被染成蓝色,则说明不能选则i,如果j已经染成红色,则说明可以。

          那么这些后继就可以被选择。如果选择i的时候失败了,那么必定要选择~i,如果也失败,则说明无解。否则

          按次序选取下一个未被染色的点。时间复杂度O(nm)。

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
using namespace std;
#define clr(x)memset(x,0,sizeof(x))
#define R 1
#define B 2
#define W 0
const int maxn = 16005;

struct node
{
    int to, next;
}e[100000];
int head[maxn];
int tot;

void add(int s, int t)
{
    e[tot].to = t;
    e[tot].next = head[s];
    head[s] = tot++;
}

int cnt;
int col[maxn];
int ans[maxn];

int n, m;
bool dfs(int u)
{
    if (col[u] == B)
        return false;
    if (col[u] == R)
        return true;
    col[u] = R;
    col[u^1] = B;
    ans[cnt++] = u;
    int i;
    int k;
    for (i=head[u]; i; i=e[i].next)
    {
        k = e[i].to;
        if (!dfs(k))
            return false;
    }
    return true;
}
bool solve()
{
    int i, j;
    memset(col,0,sizeof(col));
    for (i=0; i<n; i++){
        if (col[i])
            continue;
        cnt = 0;
        if (!dfs(i))
        {
            for (j=0; j<cnt; j++)
            {
                col[ans[j]] = W;
                col[ans[j]^1] = W;
            }
            if (!dfs(i^1))
                return false;
        }
    }
    return true;
}
int main()
{
    while (scanf("%d %d",&n, &m)!=EOF)
    {
        n <<= 1;
        int i;
        tot = 1;
        clr(head);
        int a, b;
        while (m--)
        {
            scanf("%d %d",&a, &b);
            a--;
            b--;
            add(a, b^1);
            add(b, a^1);
        }

        if (solve())
        {
            for (i=0; i<n; i++)
                if(col[i] == R)
                    printf("%d\n",i+1);
        }
        else printf("NIE\n");
    }
    return 0;
}

 

 

 

 

posted @ 2012-11-03 23:57  'wind  阅读(758)  评论(0编辑  收藏  举报