【BZOJ1202】【HNOI2005】狡猾的商人(並查集)

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

2

3 3

1 2 10

1 3 -5

3 3 -15

5 3

1 5 100

3 5 50

1 2 51

Sample Output

true

false

題解:給出[a,b]的和,再給出[b,c]的和,如果已知[a,c]的和,加一下就可以知道賬本的真假。每輸入一個[l,r],用並查集維護[root,l]和[root,r],查詢的時候相減即可。

代碼如下:

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
#define ll long long
#define inf 0x7f7f7f7f
#define N 1005
using namespace std;
int fa[N],v[N],n,m,t;  
bool flag;  
int find(int x)  
{  
    if(fa[x]==x) return x;  
    int tmp=find(fa[x]);  
    v[x]+=v[fa[x]];  
    fa[x]=tmp;  
    return fa[x];  
}  
void unio(int x,int y,int z)  
{  
    int p=find(x),q=find(y);  
    if(p!=q)  
    {  
        fa[p]=q;  
        v[p]=v[y]-v[x]-z;  
    }  
    else if(v[y]-v[x]!=z) flag=1;  
}  
int main()  
{  
    scanf("%d",&t);  
    while(t--)  
    {  
        memset(v,0,sizeof(v));  
        scanf("%d%d",&n,&m);  
        flag=0;  
        for(int i=0;i<=n;i++) fa[i]=i;  
        for(int i=1;i<=m;i++)  
        {  
            int x,y,z;  
            scanf("%d%d%d",&x,&y,&z);  
            if(!flag) unio(x-1,y,z);  
        }  
        if(flag) printf("false\n");  
        else printf("true\n");  
    }  
    return 0;  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章