BZOJ 1202 狡猾的商人 差分约束or带权并查集
题目链接:
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带权并查集的更多相关文章
- BZOJ 2333 棘手的操作(离线+线段树+带权并查集)
这题搞了我一天啊...拍不出错原来是因为极限数据就RE了啊,竟然返回WA啊.我的线段树要开8倍才能过啊... 首先可以发现除了那个加边操作,其他的操作有点像线段树啊.如果我们把每次询问的联通块都放在一 ...
- BZOJ 3376 [Usaco2004 Open]Cube Stacking 方块游戏(带权并查集)
题解 #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #in ...
- BZOJ 1202: [HNOI2005]狡猾的商人( 差分约束 )
好像很多人用并查集写的... 前缀和, 则 sumt - sums-1 = v, 拆成2条 : sumt ≤ sums-1 + v, sums-1 ≤ sumt - v 就是一个差分约束, 建图跑SP ...
- 【bzoj 1202】[HNOI2005] 狡猾的商人(图论--带权并查集+前缀和)
题意:一个账本记录了N个月以来的收入情况,现在有一个侦探员不同时间偷看到M段时间内的总收入,问这个账本是否为假账. 解法:带权并查集+前缀和. 判断账本真假是通过之前可算到的答案与当前读入的值是否 ...
- BZOJ.4500.矩阵(差分约束 SPFA判负环 / 带权并查集)
BZOJ 差分约束: 我是谁,差分约束是啥,这是哪 太真实了= = 插个广告:这里有差分约束详解. 记\(r_i\)为第\(i\)行整体加了多少的权值,\(c_i\)为第\(i\)列整体加了多少权值, ...
- Bzoj1202/洛谷P2294 [HNOI2005]狡猾的商人(带权并查集/差分约束系统)
题面 Bzoj 洛谷 题解 考虑带权并查集,设\(f[i]\)表示\(i\)的父亲(\(\forall f[i]<i\)),\(sum[i]\)表示\(\sum\limits_{j=fa[i]} ...
- luogu 2294 狡猾的商人 带权并查集
此题做法多啊 带权并查集,区间dp,前缀和,差分约束 1.自己写的前缀和, 11 #include<bits/stdc++.h> #define rep(i,x,y) for(regist ...
- 【bzoj1202】[HNOI2005]狡猾的商人 带权并查集
题目描述 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), .当 Ai大于0时表 ...
- luogu 2294 [HNOI2005]狡猾的商人 差分约束
一个差分约束模型,只需判一下有没有负环即可. #include <bits/stdc++.h> #define N 103 #define M 2004 #define setIO(s) ...
随机推荐
- laravel5.4学习--laravel目录结构
Laravel目录结构分析 app目录:主要是存放自己开发的应用代码(里面主要书写 控制器和模型和路由文件) bootstrap目录:laravel启动目录 config目录:主要是存放配置文件信息 ...
- [转]TEC1401.Report开发技术总结 - 第三章 使用Oracle Reports开发报表-创建一个分组报表(2/4)
本文转自:http://blog.csdn.net/deepsea_allen/article/details/53900284 第三章 创建一个分组报表 1. 建立数据模型 数据模型用于 ...
- Cannot find module 'rxjs/operators/share'
描述: ionic项目,在使用了ngx-translate之后,项目编译完成,运行到浏览器时,出现如下错误: 其中ngx-translate参照官网最新教程使用,并且也尝试了angular4.3之前的 ...
- Struts2页面开发中常用标签使用说明
1. Struts2页面开发中常用标签使用说明 1.1.往action里传值的使用方式: <input name="userName" type="text&quo ...
- SQL Serever学习15——进阶
特别说明:在sqlserver2014中,不区分大小写,也就是说,SQL是大小写不敏感的 数据库模型3类: 层次模型 网状模型 关系模型 关系型数据库语言3种: DDL数据定义语言 CREATE(创建 ...
- 【9】log4net 实例
一.创建项目并添加nuget: Install-Package log4net 二.添加配置文件 <configuration> <configSections> < ...
- Java Calendar Date使用总结
Java Calendar Date使用总结 package cn.outofmemory.codes.Date; import java.util.Calendar; import java.uti ...
- is_array判断是否为数组
if(is_array($arr)){ echo "是数组"; }else{ echo "不是数组"; }
- Mycat中间件
数据库中间件Mycat自我介绍 一.mycat概述 1.功能介绍 mycat一个开源的分布式数据库系统,是一个实现了mysql协议的server前端用户可以把它看成一个数据库代理,用mysql客户端工 ...
- kernel update
CentOS/RHEL更新包:https://rhn.redhat.com/errata/RHSA-2017-1382.html yum makecache --更新源 yum update sudo ...