【ZOJ】2770 Burn the Linked Camp 差分约束

传送门:【ZOJ】2770 Burn the Linked Camp


题目分析:

这题差分约束相对简单了不少啊。

设x[ i ]为第 i 个大营实际有的人数,s[ i ]为1~i个大营实际有的人数之和,c[ i ]为第i个大营最多能有的人数。

根据上面的信息我们能轻易列出不等式:

s[ i ] - s[ i - 1] >= 0

s[ i ] - s[ i - 1] <= c[ i ] ==> s[ i - 1] - s[ i ] >= -c[ i ]

s[ i ] - s[ j ] >= k[ i , j ] (k[ i , j ]为i~j至少有的人数)

然后对所有形如xj - xi >= ci的不等式建边( i , j , ci )。

现在我们需要明确我们到底要求什么。

其实我们要求的就是s[ n ] - s[ 0 ] = M 的最小值,即s[ n ] - s[ 0 ] >= M,为此必须当M取到最大值的时候也要满足,所以我们需要求的就是M的最大值,当且M取到最大值时,不等式s[ n ] - s[ 0 ] 取到一定满足题意的最小值。因此我们需要求的就是从0到n的最长路,d[ n ]即所求答案。需要注意的是如果图中存在正权环(即一个点入队列n+1次)无解。


代码如下:


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;

#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )

const int MAXN = 1005 ;
const int MAXQ = 1005 ;
const int MAXE = 100000 ;
const int INF = 0x3f3f3f3f ;

struct Edge {
	int v , c ;
	Edge *n ;
} ;

Edge E[MAXE] , *H[MAXN] , *cur , *pre ;
int d[MAXN] ;
int Q[MAXQ] , head , tail ;
bool inq[MAXN] ;
int in[MAXN] ;
int n , m ;

void addedge ( int u , int v , int c ) {
	cur -> v = v ;
	cur -> c = c ;
	cur -> n = H[u] ;
	H[u] = cur ++ ;
}

int spfa () {
	FOR ( i , 0 , n ) d[i] = -INF ;
	CLR ( inq , 0 ) ;
	CLR ( in , 0 ) ;
	head = tail = 0 ;
	d[0] = 0 ;
	Q[tail ++] = 0 ;
	while ( head != tail ) {
		int u = Q[head ++] ;
		inq[u] = 0 ;
		if ( head == MAXQ ) head = 0 ;
		for ( Edge *e = H[u] ; e ; e = e -> n ) {
			int v = e -> v , c = e -> c ;
			if ( d[v] < d[u] + c ) {
				d[v] = d[u] + c ;
				if ( !inq[v] ) {
					inq[v] = 1 ;
					if ( ++ in[v] > n ) return 0 ;
					Q[tail ++] = v ;
					if ( tail == MAXQ ) tail = 0 ;
				}
			}
		}
	}
	return 1 ;
}

void solve () {
	int u , v , c ;
	cur = E ;
	CLR ( H , 0 ) ;
	FOR ( i , 1 , n ) {
		scanf ( "%d" , &c ) ;
		addedge ( i - 1 , i , 0 ) ;
		addedge ( i , i - 1 , -c ) ;
	}
	while ( m -- ) {
		scanf ( "%d%d%d" , &u , &v , &c ) ;
		addedge ( u - 1 , v , c ) ;
	}
	if ( spfa () ) printf ( "%d\n" , d[n] ) ;
	else printf ( "Bad Estimations\n" ) ;
}

int main () {
	while ( ~scanf ( "%d%d" , &n , &m ) ) solve () ;
	return 0 ;
}


你可能感兴趣的:(ZOJ)