HDU 4421 Bit Magic【2-SAT】

来源:互联网 发布:现在淘宝卖什么好 编辑:程序博客网 时间:2024/05/28 05:18

题目链接

裸的2-SAT问题,学习了一下如何套模板。要找到矛盾,如果A则不能B,就把A和B加入边。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;#define ll long longconst int MAXN = 505 * 2;//逻辑变量的个数const int MAXM = 505 * 505 * 3; //表达式的个数struct Edge {    int to, next;} edge[MAXM];int head[MAXN], cntE;void init() {    cntE = 0;    memset(head, -1, sizeof head);}void addedge(int u, int v) {    edge[cntE].to = v;    edge[cntE].next = head[u];    head[u] = cntE++;}bool vis[MAXN];int stk[MAXN], top;bool dfs(int u) {    if (vis[u ^ 1]) return false;    if (vis[u]) return true;    vis[u] = true; stk[top++] = u;    for (int i = head[u]; ~i; i = edge[i].next) {        if (!dfs(edge[i].to)) return false;    }    return true;}inline bool sat(int n) {    memset(vis, false, sizeof vis);    for (int i = 0; i < n; ++i) {        if (vis[i] || vis[i ^ 1]) continue;        top = 0;        if (!dfs(i)) {            while (top) vis[stk[--top]] = false;            if (!dfs(i ^ 1)) return false;        }    }    return true;}ll b[505][505];int N;int getw(int w, ll s){    ll jd = 1 << w;    return (jd & s) >> w;}void addkind(int w, ll s, int i, int j, int kind){    i *= 2;    j *= 2;    int p = getw(w, s);    if (kind == 1)     // |    {        if (p)        {            addedge(i ^ 1, j);            addedge(j ^ 1, i);        }        else        {            addedge(i ^ 1, j ^ 1);            addedge(j ^ 1, i ^ 1);        }    }    else if (kind == 2)// &    {        if (p)        {            addedge(i, j);            addedge(j, i);        }        else        {            addedge(i, j ^ 1);            addedge(j, i ^ 1);        }    }    else if (kind == 3)// ^    {        if (p)        {            addedge(i, j ^ 1);            addedge(i ^ 1, j);            addedge(j, i ^ 1);            addedge(j ^ 1, i);        }        else        {            addedge(i ^ 1, j ^ 1);            addedge(i, j);            addedge(j ^ 1, i ^ 1);            addedge(j, i);        }    }}bool ok(int w)//第w位{    for (int i = 0; i < N; i++)    {        for (int j = 0; j < N; j++)        {            if (i == j)            {                if (b[i][j] != 0)                    return false;            }            else if (i % 2 == 1 && j % 2 == 1)//   |                addkind(w, b[i][j], i, j, 1);            else if (i % 2 == 0 && j % 2 == 0)//   &                addkind(w, b[i][j], i, j, 2);            else                              //   ^                addkind(w, b[i][j], i, j, 3);        }    }    return sat(N * 2);}int main(){    while (scanf("%d", &N) != EOF)    {        for (int i = 0; i < N; i++)            for (int j = 0; j < N; j++)                scanf("%lld", &b[i][j]);        bool flag = true;        for (int w = 0; w <= 31; w++)        {            init();            if (ok(w) == false)            {                flag = false;                break;            }        }        if (flag)   printf("YES\n");        else    printf("NO\n");    }    return 0;}