1202: [HNOI2005]狡猾的商人(差分约束)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1202

据说这道题可以用并查集来做,但是太神奇我太弱不会,就只能水水的用差分约束水过去了。

令账目的前缀和为pre[],那么对于每一个信息pre[t]-pre[s-1]=v

即pre[t]-pre[s-1]<=v&&pre[t]-pre[s-1]>=v,然后就SPFA来搞差分约束就可以拉。

代码:

#include 
#include 
#include 
#include 
 
using namespace std ;
 
#define MAXN 110
 
struct edge {
    edge *next ;
    int t , d ;
} *head[ MAXN ] ;
 
void AddEdge( int s , int t , int d ) {
    edge *p = new( edge ) ;
    p -> t = t , p -> d = d , p -> next = head[ s ]    ;
    head[ s ] = p ;
}
 
int n , m , w ;
 
stack < int > S ;
int dist[ MAXN ] , cnt[ MAXN ] ;
bool f[ MAXN ] ;
 
bool spfa(  ) {
    while ( ! S.empty(  ) ) S.pop(  ) ;
    for ( int i = 0 ; i <= n ; i ++ ) dist[ i ] = 0 , cnt[ i ] = 1 , S.push( i ) ;
    memset( f , true , sizeof( f ) ) ;
    while ( ! S.empty(  ) ) {
        int v = S.top(  ) ; S.pop(  ) , f[ v ] = false ;
        for ( edge *p = head[ v ] ; p ; p = p -> next ) if ( dist[ p -> t ] > dist[ v ] + p -> d ) {
            if ( ( ++ cnt[ p -> t ] ) > n + 1 ) return false ;
            dist[ p -> t ] = dist[ v ] + p -> d ;
            if ( ! f[ p -> t ] ) f[ p -> t ] = true , S.push( p -> t ) ;
        }
    }
    return true ;
}
 
int main(  ) {
    scanf( "%d" , &w ) ;
    while ( w -- ) {
        memset( head , 0 , sizeof( head ) ) ;
        scanf( "%d%d" , &n , &m ) ;
        while ( m -- ) {
            int s , t , v ; scanf( "%d%d%d" , &s , &t , &v ) ;
            AddEdge( s - 1 , t , v ) , AddEdge( t , s - 1 , - v ) ;
        }
        printf( spfa(  ) ? "true\n" : "false\n" ) ;
    }
    return 0 ;
}

你可能感兴趣的:(1202: [HNOI2005]狡猾的商人(差分约束))