BZOJ1202 [HNOI2005]狡猾的商人 【并查集】
1202: [HNOI2005]狡猾的商人
Time Limit:?10 Sec??Memory Limit:?162 MBSubmit:?4180??Solved:?2015
[Submit][Status][Discuss]
Description
刁姹接到一個任務,為稅務部門調查一位商人的賬本,看看賬本是不是偽造的。賬本上記錄了n個月以來的收入情況,其中第i 個月的收入額為Ai(i=1,2,3...n-1,n), 。當 Ai大于0時表示這個月盈利Ai 元,當 Ai小于0時表示這個月虧損Ai 元。所謂一段時間內的總收入,就是這段時間內每個月的收入額的總和。 刁姹的任務是秘密進行的,為了調查商人的賬本,她只好跑到商人那里打工。她趁商人不在時去偷看賬本,可是她無法將賬本偷出來,每次偷看賬本時她都只能看某段時間內賬本上記錄的收入情況,并且她只能記住這段時間內的總收入。 現在,刁姹總共偷看了m次賬本,當然也就記住了m段時間內的總收入,你的任務是根據記住的這些信息來判斷賬本是不是假的。
Input
第一行為一個正整數w,其中w < 100,表示有w組數據,即w個賬本,需要你判斷。每組數據的第一行為兩個正整數n和m,其中n < 100,m < 1000,分別表示對應的賬本記錄了多少個月的收入情況以及偷看了多少次賬本。接下來的m行表示刁姹偷看m次賬本后記住的m條信息,每條信息占一行,有三個整數s,t和v,表示從第s個月到第t個月(包含第t個月)的總收入為v,這里假設s總是小于等于t。
Output
包含w行,每行是true或false,其中第i行為true當且僅當第i組數據,即第i個賬本不是假的;第i行為false當且僅當第i組數據,即第i個賬本是假的。
Sample Input
23 3
1 2 10
1 3 -5
3 3 -15
5 3
1 5 100
3 5 50
1 2 51
Sample Output
truefalse
我圖形思維還是太弱了QAQ
短短并查集查了那么久
由題,只有當我們直接或間接得到兩個相同的區間信息不同時為false
按照前綴和的思想,區間和[a,b] = z可以寫成s[b] - s[a - 1] = z
這樣子我們就轉化為了兩個點之間的關系,每當我們得出兩點的關系時,我們將它們所在集合合并
兩點關系確定,當且僅當兩點在同一并查集中
我們再維護每一點到所在并查集根節點的距離表示s[a] - s[root]
這樣當我們需要b - a的時,只需將d[b] - d[a]
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long int #define REP(i,n) for (int i = 1; i <= (n); i++) #define fo(i,x,y) for (int i = (x); i <= (y); i++) #define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next) using namespace std; const int maxn = 105,maxm = 100005,INF = 1000000000; inline int read(){int out = 0,flag = 1;char c = getchar();while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}return out * flag; } int pre[maxn],d[maxn],n,m; inline int find(int u){if (u == pre[u]) return u;int fa = find(pre[u]);d[u] += d[pre[u]];pre[u] = fa;return fa; } void init(){n = read(); m = read();for (int i = 0; i <= n; i++) pre[i] = i,d[i] = 0; } int main() {int T = read(),a,b,fa,fb,z;bool flag;while (T--){init(); flag = true;while (m--){a = read() - 1; b = read(); z = read(); fa = find(a); fb = find(b);if (fa != fb){d[fa] = d[b] - d[a] - z;pre[fa] = fb;}else if (d[b] - d[a] != z) flag = false;}if (flag) printf("true\n");else printf("false\n");}return 0; }
轉載于:https://www.cnblogs.com/Mychael/p/8282808.html
總結
以上是生活随笔為你收集整理的BZOJ1202 [HNOI2005]狡猾的商人 【并查集】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qtcreator 之中文目录
- 下一篇: 重构手法之简化函数调用【1】