2-sat问题,只需要判断yes或no
所以可以直接连边,缩点,判断同一组的是否在同一个块中。
1 #include <cstdio> 2 #include <stack> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #define N 1000001 7 8 int n, m, cnt, idx, sz; 9 int head[N], to[N << 1], next[N << 1], dfn[N], low[N], belong[N]; 10 bool ins[N], flag; 11 std::stack <int> s; 12 13 inline void add(int x, int y) 14 { 15 to[cnt] = y; 16 next[cnt] = head[x]; 17 head[x] = cnt++; 18 } 19 20 inline void tarjan(int u) 21 { 22 int i, v; 23 dfn[u] = low[u] = ++idx; 24 ins[u] = 1; 25 s.push(u); 26 for(i = head[u]; i != -1; i = next[i]) 27 { 28 v = to[i]; 29 if(!dfn[v]) 30 { 31 tarjan(v); 32 low[u] = std::min(low[u], low[v]); 33 } 34 else if(ins[v]) low[u] = std::min(low[u], dfn[v]); 35 } 36 if(low[u] == dfn[u]) 37 { 38 ++sz; 39 do 40 { 41 v = s.top(); 42 s.pop(); 43 ins[v] = 0; 44 belong[v] = sz; 45 }while(u != v); 46 } 47 } 48 49 int main() 50 { 51 int i, j, a, b, c, d; 52 while(~scanf("%d", &n)) 53 { 54 memset(head, -1, sizeof(head)); 55 memset(ins, 0, sizeof(ins)); 56 memset(dfn, 0, sizeof(dfn)); 57 idx = cnt = sz = 0; 58 while(!s.empty()) s.pop(); 59 scanf("%d", &m); 60 for(i = 1; i <= m; i++) 61 { 62 scanf("%d %d %d %d", &a, &b, &c, &d); 63 a = (a << 1) + c; 64 b = (b << 1) + d; 65 add(a, b ^ 1); 66 add(b, a ^ 1); 67 } 68 for(i = 0; i < n << 1; i++) 69 if(!dfn[i]) 70 tarjan(i); 71 flag = 0; 72 for(i = 0; i < n; i++) 73 if(belong[i << 1] == belong[(i << 1) ^ 1]) 74 flag = 1; 75 if(flag) printf("NO\n"); 76 else printf("YES\n"); 77 } 78 return 0; 79 }
时间: 2024-11-03 22:38:42