【bzoj 1202】[HNOI2005] 狡猾的商人(图论--带权并查集+前缀和)

题意:一个账本记录了N个月以来的收入情况,现在有一个侦探员不同时间偷看到M段时间内的总收入,问这个账本是否为假账。

解法:带权并查集+前缀和。
   判断账本真假是通过之前可算到的答案与当前读入的值是否相同来完成。那么就是只有知道新读入的区间2端的(在相同区域内的!!)前缀和才可以判断,也就是这2个端点之前被纳入了相同的区域内才可以判断。于是,我们就可以想到并查集了。(( ′? ??`) 真的么......)
   假设已知x~y月的总收入为d,那么s[y]-s[x-1]=d。一般前缀和是算上自己的,这里我理解s[i]为在 i 所在的区域内 i 之前的数的大小。接着,当x,y不在相同区域内时就将其合并,在时就判断。

P.S.网上似乎还有人用查分约束的方法做。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 using namespace std;
 6
 7 const int N=105,M=1005;
 8 int n,m;
 9 int fa[N],f[N];
10 bool flag;
11
12 int ffind(int x)
13 {
14     if (fa[x]!=x)
15     {
16       int fx=fa[x];
17       fa[x]=ffind(fx);
18       f[x]+=f[fx];
19     }
20     return fa[x];
21 }
22 void ins(int x,int y,int d)
23 {
24     int fx=ffind(x),fy=ffind(y);
25     if (fx!=fy)
26     {
27       fa[fx]=fy;//at ease
28       f[fx]=f[y]+d-f[x];
29     }
30     else if (f[x]-f[y]!=d) flag=false;
31 }
32 int main()
33 {
34     int T;
35     scanf("%d",&T);
36     while (T--)
37     {
38       int x,y,d;
39       scanf("%d%d",&n,&m);
40       flag=true;
41       for (int i=0;i<=n;i++) fa[i]=i,f[i]=0;
42       for (int i=1;i<=m;i++)
43       {
44         scanf("%d%d%d",&x,&y,&d);//s[y]-s[x-1]=d
45         if (flag) ins(x-1,y,d);
46       }
47       if (flag) printf("true\n");
48       else printf("false\n");
49     }
50     return 0;
51 }

我再附个图好了,自己真心理解了很久很久~(┬_┬)

时间: 2024-08-03 07:27:58

【bzoj 1202】[HNOI2005] 狡猾的商人(图论--带权并查集+前缀和)的相关文章

BZOJ 1202: [HNOI2005]狡猾的商人( 差分约束 )

好像很多人用并查集写的... 前缀和, 则 sumt - sums-1 = v, 拆成2条 : sumt ≤ sums-1 + v, sums-1 ≤ sumt - v 就是一个差分约束, 建图跑SPFA.. 想起之前codeVS某场月赛T1有些人用带权并查集..然而我是差分约束水过去的... ------------------------------------------------------------------------------ #include<cstdio> #incl

bzoj 1202: [HNOI2005]狡猾的商人 并查集好题

1202: [HNOI2005]狡猾的商人 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2946  Solved: 1384[Submit][Status][Discuss] Description 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), .当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai

bzoj 1202: [HNOI2005]狡猾的商人(并查集+前缀和)

1202: [HNOI2005]狡猾的商人 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2573  Solved: 1209 [Submit][Status][Discuss] Description 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), .当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损A

【poj 1988】Cube Stacking(图论--带权并查集 模版题)

题意:有N个方块,M个操作{“C x”:查询方块x上的方块数:“M x y”:移动方块x所在的整个方块堆到方块y所在的整个方块堆之上}.输出相应的答案. 解法:带权并查集.每堆方块作为一个集合,维护3个数组:fa[x]表示x方块所在堆的最顶部的方块:d[x]表示x方块所在堆的最底部的方块:f[x]表示x方块方块x上的方块数. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<

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

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1202 [题目大意] 给出一些区间和的数值,问是否存在矛盾 [题解] 用并查集维护前缀和之间的距离,每个节点保存到根节点的数值差, 如果保存的数值差的差与前缀和之差不相等,则矛盾 [代码] #include <cstdio> #include <algorithm> using namespace std; const int N=110; int n,m,f[N],d[

BZOJ 1202 HNOI2005 狡猾的商人 并查集

题目大意:给定一个序列,m次给出一段区间的和,求这个序列是否合法 第一眼看还以为是差分约束- - [x,y]区间内和为z等价于sum[y]-sum[x-1]=z 用并查集来维护这个关系即可 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 110 using namespace std; int n,m; int fa[M],f[M]

BZOJ 1202 [HNOI2005]狡猾的商人

题解:加权并查集或差分约束 一开始并查集竟然打错了QWQ #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=100009; int T; int n,m; int father[maxn]; int ky[maxn]; int Getf(int x){ if(father[x]==x)return x; int ff=father[x]; f

1202: [HNOI2005]狡猾的商人

1202: [HNOI2005]狡猾的商人 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1554  Solved: 745[Submit][Status] Description 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), .当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai 元.所谓一段时间内的

(带权并查集) bzoj 1202

1202: [HNOI2005]狡猾的商人 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1745  Solved: 837[Submit][Status][Discuss] Description 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), .当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai 元