HDU4421 Bit Magic

来源:互联网 发布:java 私有构造方法 编辑:程序博客网 时间:2024/06/08 08:24

题目来源

题目大意

题里面那段程序是用a[n]来生成b[n][n],现在已知b[n][n],问a[n]是否存在

解题思路

许久不做图论,把这道题拿出来练练,顺便重新看了看2-SAT的建边
首先,最多一共是32位数,那么枚举每一位数,再看i,j之间的关系,然后就可以决定,如果a[i]选什么,a[j]就必须选什么
以&运算为例,如果b[i][j]那一位是1,那么就存在如下关系:a[i]选0,a[j]必然选1,a[j]选0,a[i]必然选1,那么就可以建立如下两条边:2i→2j+1,2j→2i+1,接下来的位运算同理

AC CODE

/*************************************************************************    > File Name: 6067.cc    > Author: Severus    > Mail: qinhuapeng425@163.com     > Created Time: 2014年09月11日 星期四 18时32分56秒 ************************************************************************/#include <cstdio>#include <vector>#include <cstring>#include <iostream>#include <algorithm>using namespace std;struct TwoSat {    int n, c;    vector<int> G[1010];    bool mark[1010];    int S[1010];    bool dfs(int x) {        if (mark[x ^ 1]) return 0;        if (mark[x]) return 1;        mark[x] = 1;        S[c++] = x;        for (int i = 0; i < G[x].size(); i++)             if (!dfs(G[x][i])) return 0;        return 1;    }    void init(int n) {        this->n = n;        for (int i = 0; i < n * 2; i++) G[i].clear();        memset(mark, 0, sizeof mark);    }    void add_clause(int x, int xval, int y, int yval) {        x = x * 2 + xval;        y = y * 2 + yval;        G[x^1].push_back(y);        G[y^1].push_back(x);    }    bool solve() {        for (int i = 0; i < n * 2; i += 2)             if (!mark[i] && !mark[i + 1]) {                c = 0;                if (!dfs(i)) {                    while (c > 0) mark[S[--c]] = false;                    if (!dfs(i + 1)) return false;                }            }        return true;    }};int n;int b[510][510];TwoSat solver;void solve() {    for (int i = 0; i < n; i++)        for (int j = 0; j < n; j++)            scanf("%d", &b[i][j]);    for (int k = 0; k < 31; k++) {        solver.init(n);        for (int i = 0; i < n; i++)            for (int j = i + 1; j < n; j++) {                int m = (b[i][j] >> k) & 1;                if ((i & 1) && (j & 1)) {                    if (m) solver.add_clause(i, 1, j, 1);                    else {                        solver.G[2 * i].push_back(2 * j);                        solver.G[2 * j].push_back(2 * i);                    }                } else if (!(i & 1) && !(j & 1)) {                    if (m) {                        solver.G[2 * i + 1].push_back(2 * j + 1);                        solver.G[2 * j + 1].push_back(2 * i + 1);                    }                    else solver.add_clause(i, 0, j, 0);                } else {                    if (m) {                        solver.add_clause(i, 0, j, 0);                        solver.add_clause(i, 1, j, 1);                    } else {                        solver.add_clause(i, 1, j, 0);                        solver.add_clause(i, 0, j, 1);                    }                }            }        if (!solver.solve()) {            puts("NO"); return;        }    }    puts("YES");}int main() {    while (scanf("%d", &n) == 1) solve();    return 0;}


0 0
原创粉丝点击