2-SAT模板

按字典序输出 直接dfs就好了(hdu1814(抄自 http://www.cnblogs.com/kuangbin/archive/2012/10/05/2712429.html)

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 20020;
const int MAXM = 100010;

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;
}

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;
}

int main() {
    int n, m;
    int u, v;
    while (~scanf("%d%d", &n, &m)) {
        init();
        while (m--) {
            scanf("%d%d", &u, &v);
            u--, v--;
            addedge(u, v^1); //选u就必须选择v^1
            addedge(v, u^1);
        }
        n *= 2;
        if (sat(n)) {
            for (int i = 0; i < n; ++i) {
                if (vis[i]) printf("%d\n", i+1);
            }
        } else {
            printf("NIE\n");
        }
    }
    return 0;
}

 

输出任意一组解

const int N = 1010;
const int M = 100010;

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

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;
        }
    }
}

int opp[N], ind[N], col[N]; // 相对的点 入度 染色 col[]=1选择

bool topsort(int n) // 序号从0开始
{
    for (int i = 0; i < 2*n; i += 2) {
        int k1 = kind[i]; int k2 = kind[i^1]; // 相对的两个点
        if (k1 == k2) return false;
        opp[k1] = k2; opp[k2] = k1;
    }
    memset(head, -1, sizeof head);
    int u, v;
    for (int i = 0; i < cntE; ++i) {
        u = edge[i].from, v = edge[i].to;
        if (kind[u] != kind[v]) { // 反向建图
            addedge2(kind[v], kind[u]);
            ind[kind[u]]++;
        }
    }
    queue<int> q;
    for (int i = 1; i <= cnt; ++i) if (!ind[i]) q.push(i);
    while (q.size()) {
        u = q.front(); q.pop();
        if (!col[u]) col[u] = 1, col[ opp[u] ] = -1;
        for (int i = head[u]; i != -1; i = edge2[i].next)
            if (--ind[edge2[i].to] == 0) q.push(edge2[i].to);
    }
    return true;
}

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

 

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