hdu 3062 Party 最裸2-sat题目
http://acm.hdu.edu.cn/showproblem.php?pid=3062
题意:中文...
思路:
来自伍昱的《由对称性解2-SAT问题》
http://wenku.baidu.com/view/afd6c436a32d7375a41780f2.html
把确定不矛盾的双方建立边,然后tarjan缩点。判断每一对夫妻是否属于不同的环,如果存在同一环里,则无解,否则有解
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define inf 0x7f7f7f7f #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x)int #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define N 2005 using namespace std; int dfn[N],low[N]; int belong[N],stk[N]; bool ins[N]; int cnt,idx,top; vector<int>iVc[N]; int n,m; void tarjan(int u) { int j; dfn[u] = low[u] = ++idx; stk[++top] = u; ins[u] = true; int sz = iVc[u].size(); for (j = 0; j < sz; ++j) { int v = iVc[u][j]; if (dfn[v] == -1) { tarjan(v); low[u] = min(low[u],low[v]); } else if (ins[v]) { low[u] = min(low[u],dfn[v]); } } if (dfn[u] == low[u]) { cnt++; do { j = stk[top--]; ins[j] = false; belong[j] = cnt; }while (j != u); } } void solve() { int i; //tarjan缩点 for (i = 0; i < 2*n; ++i) { if (dfn[i] == -1) { tarjan(i); } } //判断夫妻是否属于同一环 bool flag = false; for (i = 0; i < n; ++i) { if (belong[2*i] == belong[2*i + 1]) { flag = true; break; } } if (!flag) printf("YES\n"); else printf("NO\n"); } void init() { int i; for (i = 0; i <= 2*n; ++i) { iVc[i].clear(); dfn[i] = low[i] = -1; ins[i] = false; } top = idx = cnt = 0; } int main() { int i; int a1,a2,b1,b2; while (~scanf("%d%d",&n,&m)) { init(); for (i = 0; i < m; ++i) { //不矛盾的建边 scanf("%d%d%d%d",&a1,&a2,&b1,&b2); iVc[a1*2 + b1].push_back(a2*2 + 1 - b2); iVc[a2*2 + b2].push_back(a1*2 + 1 - b1); } solve(); } return 0; }