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