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