您的位置:首页 > 其它

【题】【并查集(带权)】NKOJ 3770 财务信息

2016-09-18 13:12 169 查看
NKOJ 3770 财务信息

时间限制 : - MS 空间限制 : 65536 KB

评测说明 : 1000ms

问题描述

某公司的账本上记录了n个月(编号1到n)的营收情况,其中第i个月的收入为Ai元。当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai 元。所谓一段时间内的总收入,就是这段时间内每个月的收入额的总和。

作为老板的你懒得去查看所有财务细节,你要求会计向你做了m次财务汇报,每次财务汇报的形式为三个整数s、t 、v,表示第s到t个月这段时间的总收入为v元。

根据财务的汇报,你要快速做出判断,这些财务汇报中是否有虚假信息。

输入格式

第一行为一个正整数w,表示有w组数据,即w个账本,需要你判断。

对于每组数据:

第一行为两个正整数n和m,分别表示对应的账本记录了多少个月的收入情况以及进行了多少次汇报。

接下来的m行表示m次汇报的信息,每条信息占一行,有三个整数s,t和v,表示从第s个月到第t个月(包含第t个月)的总收入为v,这里s总是小于等于t。

输出格式

包含w行,每行是true或者false

其中第i行为false当且仅当第i个账本的财务信息是虚假的,否则为true。

样例输入

2

3 3

1 2 10

1 3 -5

3 3 -15

5 3

1 5 100

3 5 50

1 2 51

样例输出

true

false

提示

对于30%的数据: w<=20, n<=20, m<=100

对于100% 的数据: w<=100, n<=100, m<=1000, Ai在int范围以内

来源 改编自 hnoi2005

思路:

可以将s t v看做

并查集,更新祖父关系时维护val[]

设val[s] 表示sum[be[s]]-sum[s] 的值,即s+1~be[s]月的营业额总和。

每次得到一个新的数据时,若已经在一个集合中,则算出答案,与给出的数据进行比较。/* sum[t]-sum[s-1]=(sum[be[t]-val[t])-(sum[be[s-1]]-val[s-1])=val[s-1]-val[t] */

若不再一个集合中,则合并为一个集合。

#include<cstdio>
#include<iostream>
using namespace std;
const int need=103;

int be[need];
long long val[need];

int getbe(int x)
{
if(be[x]!=x)
{
int t=getbe(be[x]);
val[x]+=val[be[x]];
return be[x]=t;
}
else return x;
}

int main()
{//freopen("a.txt","r",stdin);
int w;scanf("%d",&w);
int i,n,m,fs,ft,s,t;
long long v;
while(w)
{
w--;
bool mark=true;
scanf("%d%d",&n,&m);
for(i=0;i<=n;i++) be[i]=i,val[i]=0;//从0开始
for(i=1;i<=m;i++)
{
scanf("%d%d%I64d",&s,&t,&v);
if(!mark) continue;
s--;
fs=getbe(s),ft=getbe(t);
if(ft!=fs)
{
be[fs]=ft;
val[fs]=val[t]+v-val[s];
}
else if(val[s]-val[t]!=v) mark=false;
}
puts(mark ? "true" : "false");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: