传送门:【HDU】1811 Rank of Tetris、
题目分析:rz,这题纯粹考基本功啊,然后我各种细节错误啊。。。
基本思路是,先对相等操作做合并处理,将所有相等的接到一个点上先,然后再判断一次,如果一个集合中存在不等号,肯定是冲突了的。接下来就是按照不等号建边就行了,之后是拓扑,走一次点权最长路,如果不能遍历所有的集合,那么一定是有冲突了。如果遍历完了但是不能通过一条路遍历所有的集合,那么说明关系还不确定。最后如果最长路长度等于总点数就输出OK吧。
我一个地方写错了竟然过了自己写的N组小小数据,Orz。。。不多说了上代码吧。。。
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std ; #define REP( i , n ) for ( int i = 0 ; i < n ; ++ i ) #define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define REPV( i , a , b ) for ( int i = a ; i >= b ; -- i ) #define clear( a , x ) memset ( a , x , sizeof a ) const int MAXN = 10005 ; const int MAXQ = 10005 ; const int MAXE = 20005 ; const int INF = 0x3f3f3f3f ; struct Edge { int v , c , n ; Edge () {} Edge ( int var , int cost , int next ) : v ( var ) , c ( cost ) , n ( next ) {} } ; struct Node { int u , v , ch ; } ; Edge E[MAXE] ; Node a[MAXE] ; int hd[MAXN] , cntE ; int d[MAXN] ; int p[MAXN] ; int Q[MAXQ] ; int in[MAXN] ; int cnt[MAXN] ; int head , tail ; int NV , NE ; char s[5] ; int find ( int x ) { return p[x] == x ? x : ( p[x] = find ( p[x] ) ) ; } void addedge ( int u , int v ) { E[cntE] = Edge ( v , 0 , hd[u] ) ; hd[u] = cntE ++ ; } void DAG () { int flag = 0 , num = 0 ; head = tail = 0 ; clear ( cnt , 0 ) ; REP ( i , NV ) if ( p[i] == i && !in[i] ) Q[tail ++] = i , cnt[i] = d[i] ; while ( head != tail ) { int u = Q[head ++] ; num += d[u] ; for ( int i = hd[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( cnt[v] < cnt[u] + d[v] ) cnt[v] = cnt[u] + d[v] ; if ( 0 == ( -- in[v] ) ) Q[tail ++] = v ; } } if ( num < NV ) { printf ( "CONFLICT\n" ) ; return ; } REP ( i , NV ) if ( p[i] == i && cnt[i] == NV ) flag = 1 ; if ( flag ) printf ( "OK\n" ) ; else printf ( "UNCERTAIN\n" ) ; } void work () { int u , v ; int flag = 0 ; cntE = 0 ; REP ( i , NV ) p[i] = i , d[i] = 1 , hd[i] = -1 , in[i] = 0 ; REP ( i , NE ) { scanf ( "%d%s%d" , &a[i].u , s , &a[i].v ) ; if ( s[0] == '=' ) { int x = find ( a[i].u ) ; int y = find ( a[i].v ) ; if ( x != y ) { p[x] = y ; d[y] += d[x] ; } a[i].ch = 0 ; } if ( s[0] == '>' ) a[i].ch = 1 ; if ( s[0] == '<' ) a[i].ch = 2 ; } REP ( i , NV ) find ( i ) ; REP ( i , NE ) { if ( flag ) break ; int x = find ( a[i].u ) ; int y = find ( a[i].v ) ; if ( x == y && a[i].ch ) flag = 1 ; if ( x != y ) { if ( a[i].ch == 1 ) { addedge ( x , y ) ; ++ in[y] ; } if ( a[i].ch == 2 ) { addedge ( y , x ) ; ++ in[x] ; } } } if ( flag ) printf ( "CONFLICT\n" ) ; else DAG () ; } int main () { while ( ~scanf ( "%d%d" , &NV , &NE ) ) work () ; return 0 ; }