题目链接:

https://www.lydsy.com/JudgeOnline/problem.php?id=1202

题目大意:

刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的。账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), 。当 Ai大于0时表示这个月盈利Ai 元,当 Ai小于0时表示这个月亏损Ai 元。所谓一段时间内的总收入,就是这段时间内每个月的收入额的总和。 刁姹的任务是秘密进行的,为了调查商人的账本,她只好跑到商人那里打工。她趁商人不在时去偷看账本,可是她无法将账本偷出来,每次偷看账本时她都只能看某段时间内账本上记录的收入情况,并且她只能记住这段时间内的总收入。 现在,刁姹总共偷看了m次账本,当然也就记住了m段时间内的总收入,你的任务是根据记住的这些信息来判断账本是不是假的。

思路:

一:差分约束系统转化

对于一段区间的和,可以转化成前缀和相减的形式。

比如区间a-b的和为c,也就是sum[b] - sum[a - 1] = c

可以写成两个式子:

sum[b] - sum[a - 1] <= c

sum[b] - sum[a - 1] >= c

根据差分约束系统式子:

也就是a-1到b 权值为c

b到a-1 权值为-c

判断有没有负环,有的话无解,输出false。

二、带权并查集:

也是转化成前缀和的形式。对于每个节点所带的权值cnt[i] = s[root] - s[i]

1、如果x=a-1,y=b在同一子树中,cnt[x] = s[root] - s[x] cnt[y] = s[root] - s[y]

那么cnt[x] - cnt[y] = s[y] - s[x]判断是否等于输入值c。

2、不在同一子树,进行合并。

设fx为x子树根节点 fy为y子树根节点。

有cnt[x] = s[fx] - s[x] cnt[y] = s[fy] = s[y] 目前又给出条件:s[y] - s[x] = z;

将fy并入fx中,那么cnt[fy]应该设置成s[fx] - s[fy]

由上述三个式子可得:cnt[fy]应该设置成cnt[x] - cnt[y] - z

这样带权并查集的合并就写好了。

差分:

 #include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
#define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Mem(a) memset(a, 0, sizeof(a))
#define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
#define MID(l, r) ((l) + ((r) - (l)) / 2)
#define lson ((o)<<1)
#define rson ((o)<<1|1)
#define Accepted 0
#pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} typedef long long ll;
const int maxn = + ;
const int MOD = ;//const引用更快,宏定义也更快
const int INF = 1e9 + ;
const double eps = 1e-; struct edge
{
int v, w;
edge(){}
edge(int v, int w):v(v), w(w){}
};
vector<edge>e;
vector<int>G[maxn];
bool inq[maxn];//是否在队列中
int d[maxn];
int cnt[maxn];//入队次数
int n, m;
void addedge(int u, int v, int w)
{
e.push_back(edge(v, w));
G[u].push_back(e.size() - );
}
bool SPFA()
{
queue<int>q;
memset(inq, , sizeof(inq));
memset(cnt, , sizeof(cnt));
for(int i = ; i <= n; i++){d[i] = ; inq[] = true;q.push(i);}
while(!q.empty())
{
int u = q.front();
q.pop();
inq[u] = ;
for(int i = ; i < G[u].size(); i++)
{
int v = e[G[u][i]].v;
int w = e[G[u][i]].w;
if(d[v] > d[u] + w)
{
d[v] = d[u] + w;
if(!inq[v])
{
q.push(v);
inq[v] = ;
if(++cnt[v] > n)return true;
}
}
}
}
return false;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++)G[i].clear();
e.clear();
int u, v, w;
for(int i = ; i <= m; i++)
{
scanf("%d%d%d", &u, &v, &w);
u--;
addedge(u, v, w);
addedge(v, u, -w);
}
if(SPFA())puts("false");
else puts("true");
}
return Accepted;
}

带权并查集:

 #include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
#define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Mem(a) memset(a, 0, sizeof(a))
#define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
#define MID(l, r) ((l) + ((r) - (l)) / 2)
#define lson ((o)<<1)
#define rson ((o)<<1|1)
#define Accepted 0
#pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} typedef long long ll;
const int maxn = + ;
const int MOD = ;//const引用更快,宏定义也更快
const int INF = 1e9 + ;
const double eps = 1e-; int cnt[maxn];//cnt[i]表示s[root] - s[i]
int p[maxn];
int Find(int x)
{
if(x == p[x])return x;
int tmp = Find(p[x]);//此处不可以先路径压缩,需要更新x之后再进行路径压缩
cnt[x] += cnt[p[x]];//一开始 cnt[x] = s[p[x]] - s[x] cnt[p[x]] = s[root] - s[p[x]]
p[x] = tmp; //需要路径压缩转化成 cnt[x] = s[root] - s[x]
return p[x];
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n, m;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++)p[i] = i, cnt[i] = ;
int flag = ;
for(int i = ; i <= m; i++)
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
x--;
int fx = Find(x), fy = Find(y);
if(fx != fy)
{
//目前已知 s[y] - s[x] = z cnt[x] = s[fx] - s[x] cnt[y] = s[fy] - s[y]
//将y的根fy并入x的根fx中 那么需要设置cnt[fy] = s[fx] - s[fy]
//所以cnt[fy] = s[fx] - s[fy] = s[x] + cnt[x] - (s[y] + cnt[y]) = cnt[x] - cnt[y] - z
cnt[fy] = cnt[x] - cnt[y] - z;
p[fy] = fx;
}
else if(cnt[x] - cnt[y] != z)//验证s[y] - s[x] == z 等价于验证 cnt[x] - cnt[y] == z
{
flag = ;
}
}
if(flag)puts("false");
else puts("true");
}
return Accepted;
}

BZOJ 1202 狡猾的商人 差分约束or带权并查集的更多相关文章

  1. BZOJ 2333 棘手的操作(离线+线段树+带权并查集)

    这题搞了我一天啊...拍不出错原来是因为极限数据就RE了啊,竟然返回WA啊.我的线段树要开8倍才能过啊... 首先可以发现除了那个加边操作,其他的操作有点像线段树啊.如果我们把每次询问的联通块都放在一 ...

  2. BZOJ 3376 [Usaco2004 Open]Cube Stacking 方块游戏(带权并查集)

    题解 #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #in ...

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

    好像很多人用并查集写的... 前缀和, 则 sumt - sums-1 = v, 拆成2条 : sumt ≤ sums-1 + v, sums-1 ≤ sumt - v 就是一个差分约束, 建图跑SP ...

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

    题意:一个账本记录了N个月以来的收入情况,现在有一个侦探员不同时间偷看到M段时间内的总收入,问这个账本是否为假账. 解法:带权并查集+前缀和.   判断账本真假是通过之前可算到的答案与当前读入的值是否 ...

  5. BZOJ.4500.矩阵(差分约束 SPFA判负环 / 带权并查集)

    BZOJ 差分约束: 我是谁,差分约束是啥,这是哪 太真实了= = 插个广告:这里有差分约束详解. 记\(r_i\)为第\(i\)行整体加了多少的权值,\(c_i\)为第\(i\)列整体加了多少权值, ...

  6. Bzoj1202/洛谷P2294 [HNOI2005]狡猾的商人(带权并查集/差分约束系统)

    题面 Bzoj 洛谷 题解 考虑带权并查集,设\(f[i]\)表示\(i\)的父亲(\(\forall f[i]<i\)),\(sum[i]\)表示\(\sum\limits_{j=fa[i]} ...

  7. luogu 2294 狡猾的商人 带权并查集

    此题做法多啊 带权并查集,区间dp,前缀和,差分约束 1.自己写的前缀和, 11 #include<bits/stdc++.h> #define rep(i,x,y) for(regist ...

  8. 【bzoj1202】[HNOI2005]狡猾的商人 带权并查集

    题目描述 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), .当 Ai大于0时表 ...

  9. luogu 2294 [HNOI2005]狡猾的商人 差分约束

    一个差分约束模型,只需判一下有没有负环即可. #include <bits/stdc++.h> #define N 103 #define M 2004 #define setIO(s) ...

随机推荐

  1. 【angular5项目积累总结】表单复杂校验

    view code form.css :host { display: flex; width: 100%; height:100%; border-left:1px solid #ccc; } .i ...

  2. springmvc fileupload

    1.pom文件中fileupload的dependencyyinr <dependency> <groupId>commons-fileupload</groupId&g ...

  3. SQL Serever学习7——数据表2

    修改数据表的属性 保存数据表的修改的时候,总会弹出阻止修改的警告. 解决方法2种: 1.可以使用T-sql语句强行修改 2.工具>选项>设计器>表设计器和数据库设计器>阻止保存 ...

  4. spring mongodb分页,动态条件、字段查询

    使用MongRepository public interface VideoRepository extends MongoRepository<Video, String> { Vid ...

  5. C#图片验证码绘制

    制作验证码.也可以画弧线之类..... //新建一个网站,在后台代码中引用一个using Stystem.Drawing的命名空间 Bitmap img = , ); //制作一个宽100,高50的画 ...

  6. 中小型研发团队架构实践三:微服务架构(MSA)

    一.MSA 简介 1.1.MSA 是什么 微服务架构 MSA 是 Microservice Architect 的简称,它是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相通讯.互相 ...

  7. BZOJ4671:异或图

    传送门 直接求连通的不好做,考虑容斥 设 \(g_i\) 表示至少有 \(i\) 个连通块的方案数,\(f_i\) 表示恰好有 \(i\) 个的 那么 \[g_x=\sum_{i=x}^{n}\beg ...

  8. html5 文档元素 header footer h1h2h4

    文档元素: 用于在页面的大布局, 区分各个主体和概念. 让整体清晰, 元素有语义, 进一步代替div 具体划分图示: (参考) <hgroup> <section> <n ...

  9. react生命周期es6

    基本函数有 import React from 'react' export default class MyClass extends React.Component { constructor(p ...

  10. 自定义动画(仿Win10加载动画)

    一.源代码 源代码及demo 二.背景 先看看Win10的加载动画(找了很久才找到): CPA推广甲爪广告联盟满30日结 [点击进入] 甲爪广告联盟,提供各类高单价CPA广告 单价高 收益好 日付广告 ...