【BZOJ1202】【HNOI2005】狡猾的商人
【描述】
***姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的。账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), 。当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai 元。所谓一段时间内的总收入,就是这段时间内每个月的收入额的总和。 ***姹的任务是秘密进行的,为了调查商人的账本,她只好跑到商人那里打工。她趁商人不在时去偷看账本,可是她无法将账本偷出来,每次偷看账本时她都只能看某段时间内账本上记录的收入情况,并且她只能记住这段时间内的总收入。 现在,***姹总共偷看了m次账本,当然也就记住了m段时间内的总收入,你的任务是根据记住的这些信息来判断账本是不是假的。
w < 100,n < 100,m < 1000
【分析】
并查集。每加入一条边 ,就把两个集合并起来,如果已经再一个集合内的话,直接算出该段的值,与给出的值比较是否相等。
【代码】
/************************************************************** Problem: 1202 User: N_C_Derek Language: C++ Result: Accepted Time:216 ms Memory:1272 kb ****************************************************************/ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int father[200],g[200]; int n,m; bool ans; int find(int x) { if (father[x] == x) return x; find(father[x]); g[x] += g[father[x]]; father[x] = father[father[x]]; return father[x]; } void work(int x,int y,int d) { int x0 = find(x),y0 = find(y); if (x0 != y0) { father[x0] = y0; g[x0] = g[y] - g[x] - d; } else if (g[y] - g[x] != d) ans = false; } int main() { int Tcase; scanf("%d",&Tcase); while (Tcase --) { scanf("%d %d",&n,&m); memset(g,0,sizeof(g)); for (int i = 0;i <= n;i ++) father[i] = i,g[i] = 0; ans = true; for (int i = 1;i <= m;i ++) { int x,y,d; scanf("%d %d %d",&x,&y,&d); work(x - 1,y,d); } if (ans) printf("true\n"); else printf("false\n"); } }