【HDU】1811 Rank of Tetris 并查集+拓扑排序

传送门:【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 ;
}


你可能感兴趣的:(HDU)