差分约束做法

又是一道转换成前缀和的差分约束题,已知从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. NowCoderWannafly挑战赛3-B.遇见

    遇见 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 65536K,其他语言131072K64bit IO Format: %lld 题目描述 A和B在同一条路上,他们之间的距离为 k ...

  2. Kafka+Zookeeper集群搭建

    上次介绍了ES集群搭建的方法,希望能帮助大家,这儿我再接着介绍kafka集群,接着上次搭建的效果. 首先我们来简单了解下什么是kafka和zookeeper? Apache kafka 是一个分布式的 ...

  3. kafka数据迁移实践

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:mikealzhou 本文重点介绍kafka的两类常见数据迁移方式:1.broker内部不同数据盘之间的分区数据迁移:2.不同broker ...

  4. Windows系统下文件的概念及c语言对其的基本操作(丙)

  5. 部署Asp.net Core 项目发生502.5 或者500 没有其他提示信息

    最近将公司原来.NetCore 1.6的项目升级到.net Core 2.0首先发生 502.5的错误,包括IIS日志,Windows应用程序日志都没有记录问题始终解决不了,首先看看官网给出的解决方案 ...

  6. ajax跳转到新的jsp页面

    ajax可以实现局部刷新页面,即在不刷新整个页面的情况下更新页面的局部信息. 项目中遇到一个问题:在用户列表也,当点击某个按钮时需要去查询用户的信息,查询成功跳转到用户详情界面:查询失败,则在原页面弹 ...

  7. dede:list及dede:arclist 按权重排序的方法

    有时我们需要做文章排名,比如指定第一名到第三名在前面,这样就用到这个权重排序方法.稍改下就可以完美支持.. dede:list 的方法 1 找到"根目录\include\arc.listvi ...

  8. CSAPP 第二章随笔

    类型转换问题 (1)int -> short 二进制位高位截断,低位保持不变 (2)同类型 unsign -> sign 记住二进制位是不变的 (3)P101页提到的编译器乘法优化问题,一 ...

  9. Java之IO流学习总结【上】

    一.什么是流? 流就是字节序列的抽象概念,能被连续读取数据的数据源和能被连续写入数据的接收端就是流,流机制是Java及C++中的一个重要机制,通过流我们可以自由地控制文件.内存.IO设备等数据的流向. ...

  10. 修改ncnn的openmp异步处理方法 附C++样例代码

    ncnn刚发布不久,博主在ios下尝试编译. 遇上了openmp的编译问题. 寻找各种解决方案无果,亲自操刀. 采用std::thread 替换 openmp. ncnn项目地址: https://g ...