题目描述:有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席。在2n个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是不会同时出现在聚会上的。有没有可能会有n个人同时列席?
思路:2-SAT入门题,直接建模即可。
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 5 const int N = 20001; 6 const int M = 2000000; 7 int s[N]; 8 int head[N]; 9 bool mark[N]; 10 int n, m, e, c; 11 12 struct Edge 13 { 14 int v, next; 15 } edge[M]; 16 17 void init() 18 { 19 e = 0; 20 memset( mark, false, sizeof(mark) ); 21 memset( head, -1, sizeof(head) ); 22 } 23 24 void addEdge( int u, int v ) 25 { 26 edge[e].v = v; 27 edge[e].next = head[u]; 28 head[u] = e++; 29 } 30 31 void add_clause( int x, int x_val, int y, int y_val ) 32 { 33 x = x * 2 + x_val, y = y * 2 + y_val; 34 addEdge( x ^ 1, y ); 35 addEdge( y ^ 1, x ); 36 } 37 38 bool dfs( int x ) 39 { 40 if ( mark[x ^ 1] ) return false; 41 if ( mark[x] ) return true; 42 mark[x] = true; 43 s[c++] = x; 44 for ( int i = head[x]; i != -1; i = edge[i].next ) 45 { 46 int v = edge[i].v; 47 if ( !dfs(v) ) return false; 48 } 49 return true; 50 } 51 52 bool solve() 53 { 54 for ( int i = 0; i < 2 * n; i += 2 ) 55 { 56 if ( !mark[i] && !mark[i + 1] ) 57 { 58 c = 0; 59 if ( !dfs(i) ) 60 { 61 while ( c ) 62 { 63 mark[s[--c]] = false; 64 } 65 if ( !dfs( i + 1 ) ) 66 { 67 return false; 68 } 69 } 70 } 71 } 72 return true; 73 } 74 75 int main () 76 { 77 while ( scanf("%d", &n) != EOF ) 78 { 79 scanf("%d", &m); 80 init(); 81 while ( m-- ) 82 { 83 int a1, a2, c1, c2; 84 scanf("%d%d%d%d", &a1, &a2, &c1, &c2); 85 add_clause( a1, c1, a2, c2 ); 86 } 87 printf("%s\n", solve() ? "YES" : "NO"); 88 } 89 return 0; 90 }
时间: 2024-10-05 23:55:14