BZOJ 1202: [HNOI2005]狡猾的商人 并查集

来源:互联网 发布:卖家怎么加入爱淘宝 编辑:程序博客网 时间:2024/05/20 17:25

1202: [HNOI2005]狡猾的商人

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 3934 Solved: 1896
[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

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

HINT

Source

题解:
妈诶这道题快把我搞来崩溃了,终于调过了。果然还是太菜了。

还是考虑带权并查集,用rk[x]表示rootx到x的收益。当给出x到y的收益时,我们用rk[y]-rk[x-1]就可以得到之前的x到y的收益,(感觉有点类似于前缀和)再与这次给出的关系比较。
合并的时候我还讨论了rootx和rooty的大小,即将月份靠后的往月份靠前的上合并。这样rk的加加减减比较清晰。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define rep(i,x,y) for(int i=x;i<=y;i++)const int N = 100 + 10;const int M = 1000 + 10;int t;int n,m;int fa[N],rk[N];int find(int x){    if(x==fa[x]) return x;    int d=find(fa[x]);    rk[x]+=rk[fa[x]];    return fa[x]=d;}int link(int x,int y,int d){    int fx=find(x-1),fy=find(y);    if(fx==fy){        if(rk[y]-rk[x-1]!=d) return 1;        return 0;    }    if(fy>fx){       fa[fy]=fx;       rk[fy]+=rk[x-1]+d-rk[y];    }    else{        fa[fx]=fy;        rk[fx]+=rk[y]-rk[x-1]-d;    }    return 0;}int T;bool flag=true;void update() {flag=true;}int main(){    scanf("%d",&T);    while(T--){        update();        scanf("%d%d",&n,&m);        rep(i,1,n) fa[i]=i,rk[i]=0;        rep(i,1,m){           int u,v,w;           scanf("%d%d%d",&u,&v,&w);           if(flag==false) continue;           if(link(u,v,w)) {flag=false;printf("false\n");}           //rep(j,1,n) printf("%d ",rk[j]);           //printf("\n");        }        if(flag==true) printf("true\n");    }    return 0;}
阅读全文
0 0
原创粉丝点击