pku3678 Katu Puzzle 2-sat判断是否存在可行解

http://poj.org/problem?id=3678

题意:

给定n个点,这些点只能取0或1。然后给出m条边,每条边四个变量 a,b,c,op  op的取值为(AND,OR,XOR) 问是否存在一组解X0,X1,....Xn-1使得每条边满足Xa op Xb = c  Xa,Xb表示每条边的端点。

思路:

2-sat。 将每个顶点i拆分成两个点,2*i和2*i +1 分表表示0,1。然后根据已知条件建图。建图的思想不是很清晰给出过程:

(1) A and B = 0 添加弧 A->!B , B->!A

(2)A and B = 1 !A->A , !B->B

(3)A or B = 0 A->!A , B->!B

(4)A or B = 1 !A->B , !B->A

(5)A xor B = 0 A->B , B->A , !A->!B ,!B->!A

(6)A xor B = 1 A->!B, B->!A,!B->A,!A->B

然后就是2-sat判断有无解了。
//#pragma comment(linker,"/STACK:327680000,327680000")

#include <iostream>

#include <cstdio>

#include <cmath>

#include <vector>

#include <cstring>

#include <algorithm>

#include <string>

#include <set>

#include <functional>

#include <numeric>

#include <sstream>

#include <stack>

#include <map>

#include <queue>



#define CL(arr, val)    memset(arr, val, sizeof(arr))



#define ll long long

#define inf 0x7f7f7f7f

#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define ll long long

#define L(x)    (x) << 1

#define R(x)    (x) << 1 | 1

#define MID(l, r)   (l + r) >> 1

#define Min(x, y)   (x) < (y) ? (x) : (y)

#define Max(x, y)   (x) < (y) ? (y) : (x)

#define E(x)        (1 << (x))

#define iabs(x)     (x) < 0 ? -(x) : (x)

#define OUT(x)  printf("%I64d\n", x)

#define lowbit(x)   (x)&(-x)

#define Read()  freopen("din.txt", "r", stdin)

#define Write() freopen("dout.txt", "w", stdout);





#define N 2007

#define M 1000007

using namespace std;



struct node

{

    int v;

    int next;

}g[N*N];

int head[N],ct;



int dfn[N],low[N];

int belong[N],stk[N];

bool isn[N];

int idx,cnt,top;



int n,m;

char op[10];



void add(int u,int v)

{

    g[ct].v = v;

    g[ct].next = head[u];

    head[u] = ct++;

}

//建图是关键

void build(int u,int v,int c,char *op)

{

    if (op[0] == 'A')

    {

        if (c == 1)

        {

            add(2*u,2*u + 1);

            add(2*v,2*v + 1);

        }

        else

        {

            add(2*u + 1,2*v);

            add(2*v + 1,2*u);

        }

    }

    else if (op[0] == 'O')

    {

        if (c == 1)

        {

            add(2*u,2*v + 1);

            add(2*v,2*u + 1);

        }

        else

        {

            add(2*u + 1,2*u);

            add(2*v + 1,2*v);

        }

    }

    else if (op[0] == 'X')

    {

        if (c == 1)

        {

            add(2*u + 1,2*v);

            add(2*v,2*u + 1);

            add(2*v + 1,2*u);

            add(2*u,2*v + 1);

        }

        else

        {

            add(2*u + 1,2*v + 1);

            add(2*v + 1,2*u + 1);

            add(2*u,2*v);

            add(2*v,2*u);

        }

    }

}

void init()

{

    int i;

    for (i = 0; i < 2*n; ++i)

    {

        dfn[i] = low[i] = -1;

        belong[i] = 0;

        isn[i] = false;

    }

    idx = cnt = top = 0;

}

void tarjan(int u)

{

    int i,j;

    dfn[u] = low[u] = ++idx;

    stk[++top] = u;

    isn[u] = true;

    for (i = head[u]; i != -1; i = g[i].next)

    {

        int v = g[i].v;

        if (dfn[v] == -1)

        {

            tarjan(v);

            low[u] = min(low[u],low[v]);

        }

        else if (isn[v])

        {

            low[u] = min(low[u],dfn[v]);

        }

    }

    if (dfn[u] == low[u])

    {

        cnt++;

        do

        {

            j = stk[top--];

            isn[j] = false;

            belong[j] = cnt;

        } while (j != u);

    }

}

void solve()

{

    int i;

    init();

    for (i = 0; i < 2*n; ++i)

    {

        if (dfn[i] == -1) tarjan(i);

    }

    bool flag = false;

    for (i = 0; i < n; ++i)

    {

        if (belong[2*i] == belong[2*i + 1])

        {

            flag = true;

            break;

        }

    }

    if (flag) printf("NO\n");

    else printf("YES\n");

}

int main()

{

    //Read();

    int i ;

    int x,y,z;

    while (~scanf("%d%d",&n,&m))

    {

        CL(head,-1); ct = 0;

        for (i = 0; i < m; ++i)

        {

            scanf("%d%d%d%s",&x,&y,&z,op);

            build(x,y,z,op);

        }

        solve();

    }

    return 0;

}

  

 

你可能感兴趣的:(pku)