差分约束做法

又是一道转换成前缀和的差分约束题,已知从s月到t月的收入w,设数组pre[i]代表从开始到第i个月的总收入

构造差分不等式 $ pre[s-1]-pre[t]==w $

为了满足松弛操作,我们将不等式转化成 $ pre[s-1]-pre[t]>=w $

这样建图以后我们发现当且仅当图中出现正环或负环时,账本为假,

我们可以直接在建图时加入一条反向的权值相反的边,这样直接判断负环即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define RST(a) memset((a),0,sizeof((a)))
using namespace std;
int init(){
int rv=0,fh=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
rv=(rv<<1)+(rv<<3)+c-'0';
c=getchar();
}
return fh*rv;
}
int T,head[10005],nume,dis[10005];
bool f[10005];
struct edge{
int to,nxt,dis;
}e[10005];
void adde(int from,int to,int dis){
e[++nume].to=to;
e[nume].dis=dis;
e[nume].nxt=head[from];
head[from]=nume;
}
bool dfs_SPFA(int u){
f[u]=1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(dis[v]>dis[u]+e[i].dis){
dis[v]=dis[u]+e[i].dis;
if(f[v]) return 1;
if(dfs_SPFA(v)) return 1;
}
}
f[u]=0;
return 0;
}
int main(){
freopen("in.txt","r",stdin);
T=init();
while(T--){
RST(dis);RST(head);RST(e);nume=0;RST(f);
int n=init(),m=init();
for(int i=1;i<=m;i++){
int u=init(),v=init(),di=init();
adde(u-1,v,di);
adde(v,u-1,-di);
}
bool fff=0;
for(int i=0;i<=n;i++){
if(dfs_SPFA(i)) {fff=1;break;}
}
if(fff) printf("false\n");
else printf("true\n");
}
fclose(stdin);
return 0;
}

并查集做法

本题也可以维护一个带权并查集,

fa[i]表示i号元素的父亲节点,root[i]表示i所在并查集的代表元,dis[i]=pre[i]-pre[root[i]]。所以我们可以维护一个带权并查集。

并查集的两个关键操作,查询和合并

find:

带权并查集的一般写法,更新父节点时,一并更新dis[].

因为原来\(dis[x]=pre[x]-pre[fa[x]]\),更新后\(dis[fa[x]]=pre[fa[x]]-pre[root[x]]\),所以 \(dis[x]+=dis[fa[x]]\)就更新完成了。

merge

如果读入的两个点在同一个并查集中,判断dis[u-1]-dis[v]是否等于w,若不等于,则为假。

如果不在同一个并查集中,使\(fa[root[u-1]]=root[v]\).

注意,此处为了保证合并以后原有的数量关系不发生改变,要注意 dis[root[u-1]]更新的时候加上的数值,可以在本上画一下。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define RST(a) memset((a),0,sizeof((a)))
using namespace std;
int init(){
int rv=0,fh=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
rv=(rv<<1)+(rv<<3)+c-'0';
c=getchar();
}
return fh*rv;
}
int T,fa[10005],dis[10005];
int find(int x){
if(fa[x]!=x){
int t=find(fa[x]);
dis[x]+=dis[fa[x]];
fa[x]=t;
}
return fa[x];
}
int main(){
freopen("in.txt","r",stdin);
T=init();
while(T--){
bool fff=0;
RST(fa);RST(dis);
int n=init(),m=init();
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++){
int u=init(),v=init(),w=init();
int r1=find(u-1),r2=find(v);
if(r1==r2){
if(!fff&&dis[v]-dis[u-1]!=w) fff=1,printf("false\n");
}else{
fa[r1]=r2;
dis[r1]=dis[v]-dis[u-1]-w;
}
}
if(!fff) printf("true\n");
}
fclose(stdin);
return 0;
}

洛谷 [p2294] [HNOI2005] 狡猾的商人的更多相关文章

  1. 洛谷P2294 [HNOI2005]狡猾的商人

    P2294 [HNOI2005]狡猾的商人 题目描述 输入输出格式 输入格式: 从文件input.txt中读入数据,文件第一行为一个正整数w,其中w < 100,表示有w组数据,即w个账本,需要 ...

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

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

  3. 题解——洛谷P2294 [HNOI2005]狡猾的商人(差分约束)

    裸的差分约束 dfs判断负环,如果有负环就false,否则就是true 注意有多组数据,数组要清空 #include <cstdio> #include <algorithm> ...

  4. [luogu P2294] [HNOI2005]狡猾的商人

    [luogu P2294] [HNOI2005]狡猾的商人 题目描述 输入输出格式 输入格式: 从文件input.txt中读入数据,文件第一行为一个正整数w,其中w < 100,表示有w组数据, ...

  5. P2294 [HNOI2005]狡猾的商人(差分约束)

    P2294 [HNOI2005]狡猾的商人 对于每个$(x,y,w)$,连边$(x-1,y,w),(y,x-1,-w)$,表示前$y$个月的收益比前$x-1$个月的收益大$w$ 这样题目就转化为询问图 ...

  6. LUOGU P2294 [HNOI2005]狡猾的商人(差分约束)

    [传送门] (https://www.luogu.org/problemnew/show/P2294) 解题思路 差分约束.先总结一下差分约束,差分约束就是解决一堆不等式混在一起,左边是差的形式,右边 ...

  7. P2294 [HNOI2005]狡猾的商人

    题目描述 输入输出格式 输入格式: 从文件input.txt中读入数据,文件第一行为一个正整数w,其中w < 100,表示有w组数据,即w个账本,需要你判断.每组数据的第一行为两个正整数n和m, ...

  8. [HNOI2005]狡猾的商人 ,神奇做法——贪心

    洛谷P2294 [HNOI2005]狡猾的商人 ,神奇做法--贪心 看到大牛都是写的差分约束或带权并查集,本蒟蒻都不太会(还是用差分约束过了的QAQ),但是想出一种贪心的策略,运用神奇的优先队列实现. ...

  9. [BZOJ1202][HNOI2005]狡猾的商人

    [BZOJ1202][HNOI2005]狡猾的商人 试题描述 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i= ...

随机推荐

  1. java线程间通信:一个小Demo完全搞懂

    版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程系列文章只是自己知识的总结梳理,都是最基础的玩意,已经掌握熟练的可以绕过. 一.从一个小Demo说起 上篇我们聊到了Java多线程的同步 ...

  2. 通俗理解TCP握手次数是三次

    理解之后,应该说是至少三次就可以保证可靠传输了. 看到网上一篇帖子http://www.cnblogs.com/TechZi/archive/2011/10/18/2216751.html是这么说的, ...

  3. Docker+Jenkins持续集成环境(2)使用docker+jenkins构建nodejs前端项目

    前文使用Docker搭建Jenkins+Docker持续集成环境我们已经搭建了基于docker+jenkins的持续集成环境,并构建了基于maven的项目.这一节,我们继续扩展功能,增加对Nodejs ...

  4. Spring注解依赖注入的三种方式的优缺点以及优先选择

    当我们在使用依赖注入的时候,通常有三种方式: 1.通过构造器来注入: 2.通过setter方法来注入: 3.通过filed变量来注入: 那么他们有什么区别吗?应该选择哪种方式更好? 三种方式的区别小结 ...

  5. UE4 TSubclassOf VS Native Pointer

    最近看到了TSubclassOf ,所以想要弄清楚跟一般指针的区别~ NativePointer    VS     UClass*      VS     TSubclassOf AActor* p ...

  6. 什么是Linux主机?

    Linux主机是基于Linux内核的服务器操作系统配置的主机(常见Linux服务器操作系统如:Redhat,CentOS,Debian,FreeBSD,Ubentu等). Linux主机采用国内功能最 ...

  7. thinkphp开发微信公众号时,验证基本配置提示请求url超时

    原因在index.php入口文件中必须有define('APP_NAME', 'Weixin'); 服务器url:http://bxu2713700584.my3w.com/Weixin/Index/ ...

  8. JavaScript实现Tab栏切换

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 京东网页上,可以看到下面这种tab栏的切换: 我们把模型抽象出来,实现一 ...

  9. UML图学习之二 类图

    类图(ClassDiagrams)是根据系统中的类以及各类之间的关系描述系统的静态视图.类图不仅显示系统内信息的结构,还描述系统内这些信息的行为.类图的一个重要目的是为其他图(如顺序图.交互图)定义一 ...

  10. Android开发之漫漫长途 XIII——Fragment最佳实践

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...