题意和方法都很简单,只是需要注意的地方很多,例如加边时起点终点可能在一个集合内,还有既冲突也不全的情况优先判断冲突。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 using namespace std; 6 7 const int N = 10000; 8 const int M = 20000; 9 int f[N]; 10 int head[N]; 11 int in[N]; 12 int n, m, e, sum; 13 14 int findf( int x ) 15 { 16 if ( f[x] != x ) f[x] = findf(f[x]); 17 return f[x]; 18 } 19 20 void union_set( int x, int y ) 21 { 22 x = findf(x), y = findf(y); 23 if ( x != y ) 24 { 25 f[x] = y; 26 } 27 } 28 29 struct Op 30 { 31 int a, b; 32 char r[2]; 33 } op[M]; 34 35 struct Edge 36 { 37 int v, next; 38 } edge[M]; 39 40 void addEdge( int u, int v ) 41 { 42 edge[e].v = v; 43 edge[e].next = head[u]; 44 head[u] = e++; 45 } 46 47 int main () 48 { 49 while ( scanf("%d%d", &n, &m) != EOF ) 50 { 51 e = 0; 52 sum = n; 53 memset( head, -1, sizeof(head) ); 54 memset( in, 0, sizeof(in) ); 55 for ( int i = 0; i < n; i++ ) f[i] = i; 56 for ( int i = 0; i < m; i++ ) 57 { 58 scanf("%d%s%d", &op[i].a, op[i].r, &op[i].b); 59 if ( op[i].r[0] == '=' ) 60 { 61 sum--; 62 union_set( op[i].a, op[i].b ); 63 } 64 } 65 bool flag0 = false; 66 for ( int i = 0; i < m; i++ ) 67 { 68 if ( op[i].r[0] == '=' ) continue; 69 int a = findf(op[i].a), b = findf(op[i].b); 70 if ( a == b ) 71 { 72 flag0 = true; 73 break; 74 } 75 if ( op[i].r[0] == '<' ) 76 { 77 addEdge( b, a ); 78 in[a]++; 79 } 80 else 81 { 82 addEdge( a, b ); 83 in[b]++; 84 } 85 } 86 if ( flag0 ) 87 { 88 puts("CONFLICT"); 89 continue; 90 } 91 queue<int> q; 92 for ( int i = 0; i < n; i++ ) 93 { 94 if ( !in[i] && f[i] == i ) q.push(i); 95 } 96 bool flag1 = false; 97 while ( !q.empty() ) 98 { 99 if ( q.size() > 1 ) flag1 = 1; 100 int u = q.front(); 101 q.pop(); 102 sum--; 103 for ( int i = head[u]; i != -1; i = edge[i].next ) 104 { 105 int v = edge[i].v; 106 in[v]--; 107 if ( in[v] == 0 ) 108 { 109 q.push(v); 110 } 111 } 112 } 113 if ( sum > 0 ) 114 { 115 puts("CONFLICT"); 116 } 117 else 118 { 119 if ( flag1 ) puts("UNCERTAIN"); 120 else puts("OK"); 121 } 122 } 123 return 0; 124 }