BZOJ 1202 狡猾的商人

题面:
刁姹接到⼀个任务,为税务部⻔调查⼀位商⼈的账本,看看账本是不是伪造的。账本上记录了n 个⽉以来的收⼊情况,其中第i 个⽉的收⼊额为Ai(i=1...n) 。当Ai0 时表示这个⽉盈利Ai 元,当Ai0 时表示这个⽉亏损Ai 元。所谓⼀段时间内的总收⼊,就是这段时间内每个⽉的收⼊额的总和。刁姹的任务是秘密进⾏的,为了调查商⼈的账本,她只好跑到商⼈那⾥打⼯。她趁商⼈不在时去偷看账本,可是她⽆法将账本偷出来,每次偷看账本时她都只能看某段时间内账本上记录的收⼊情况,并且她只能记住这段时间内的总收⼊。现在,刁姹总共偷看了m 次账本,当然也就记住了m 段时间内的总收⼊,你的任务是根据记住的这些信息来判断账本是不是假的。
每个测试点内有T<100 组数据,每组都满足n<100,m<1000 .

题解:

带权并查集,在合并的时候维护一下权值就可以了。

/*
  ID:Agreement
  LANG:C++
*/
// Invincible
#include <bits/stdc++.h>
#define rep( i , l , r ) for( int i = (l) ; i <= (r) ; ++i )
#define per( i , r , l ) for( int i = (r) ; i >= (l) ; --i )
#define erep( i , u ) for( int i = head[(u)] ; ~i ; i = e[i].nxt )
using namespace std;
const int maxn = 100 + 5;
int f[maxn] , v[maxn] , flg; 
int Find( int x ){
    if( x == f[x] ) return x;
    int t = Find( f[x] );
    v[x] += v[f[x]];
    return f[x] = t;
}
void ins( int x , int y , int w ){
    int fx = Find( x ) , fy = Find( y );
    if( fx != fy ){
        f[fx] = fy;
        v[fx] = v[y] - v[x] - w;
    }else if( v[y] - v[x] != w ) flg = 1;
} 
int main(){
    int T = 0 , N = 0 , M = 0 , x , y , w ;
    scanf("%d" , &T);
    while( T-- ){
        flg = 0;
        scanf("%d %d" , &N , &M);
        memset( v , 0 , sizeof v );
        rep( i , 0 , N ) f[i] = i;
        rep( i , 1 , M ){
            scanf("%d %d %d" , &x , &y , &w);
            ins( x - 1 , y , w );
        }
        if( flg ) puts("false");
        else puts("true");
    } 
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章