POJ 3678--Katu Puzzle(2-SAT)

感觉这题比较裸,表现出了2-sat的本质。

不过构图我想的还是太简单了,a&b=1我只连了 a1->b1,b1->a1,但其实是不对的。这样连,a0和b0可以同时选到。应该连a0->a1,b0->b1这样就能保证a0,b0都不被选到。或运算同理。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <bitset>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <map>
#include <set>
#define pk(x) printf("%d\n", x)
using namespace std;
#define PI acos(-1.0)
#define EPS 1E-6
#define clr(x,c) memset(x,c,sizeof(x))
//#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;

const int N = 1010;
const int M = 2000020;

struct Edge {
    int from, to, next;
} edge[M], edge2[M];
int head[N];
int cntE;
void addedge(int u, int v) {
    edge[cntE].from = u; edge[cntE].to = v; edge[cntE].next = head[u]; head[u] = cntE++;
}

int dfn[N], low[N], idx;
int stk[N], top;
int in[N];
int kind[N], cnt;

void tarjan(int u)
{
    dfn[u] = low[u] = ++idx;
    in[u] = true;
    stk[++top] = u;
    for (int i = head[u]; i != -1; i = edge[i].next) {
        int v = edge[i].to;
        if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
        else if (in[v]) low[u] = min(low[u], dfn[v]);
    }
    if (low[u] == dfn[u]) {
        ++cnt;
        while (1) {
            int v = stk[top--]; kind[v] = cnt; in[v] = false;
            if (v == u) break;
        }
    }
}

bool sat(int n) // 序号从0开始
{
    for (int i = 0; i < n; ++i) if (!dfn[i]) tarjan(i);
    for (int i = 0; i < n; i += 2) {
        if (kind[i] == kind[i+n]) return false;
    }
    return true;
}

void init() {
    memset(head, -1, sizeof head);
    memset(dfn, 0, sizeof dfn);
    memset(in, false, sizeof in);
    cntE = idx = top = cnt = 0;
}

int main()
{
    int n, m;
    int a, b, c;
    char op[10];
    while (~scanf("%d%d", &n, &m)) {
        init();
        while (m--) {
            scanf("%d%d%d%s", &a, &b, &c, op); // 0 1
            if (*op == 'A') {//and
                if (c == 1) {
                    addedge(a, a+n);
                    addedge(b, b+n);
                } else {
                    addedge(a+n, b);
                    addedge(b+n, a);
                }
            } else if (*op == 'X') {//xor
                if (c == 1) { //1^0=1;
                    addedge(a+n, b);
                    addedge(b+n, a);
                    addedge(a, b+n);
                    addedge(b, a+n);
                } else {
                    addedge(a+n, b+n);
                    addedge(b+n, a+n);
                    addedge(a, b);
                    addedge(b, a);
                }
            } else {//or 0|0=0
                if (c == 1) {
                    addedge(a, b+n);
                    addedge(b, a+n);
                } else {
                    addedge(a+n, a);
                    addedge(b+n, b);
                }
            }
        }
        if (sat(n)) puts("YES");
        else puts("NO");
    }
    return 0;
}

 

posted @ 2016-09-19 19:02  我不吃饼干呀  阅读(208)  评论(0编辑  收藏  举报