差分约束做法

又是一道转换成前缀和的差分约束题,已知从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. hdu_1041(Computer Transformation) 大数加法模板+找规律

    Computer Transformation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/ ...

  2. 最短路 spfa 算法 && 链式前向星存图

    推荐博客  https://i.cnblogs.com/EditPosts.aspx?opt=1 http://blog.csdn.net/mcdonnell_douglas/article/deta ...

  3. 在.Net中将RocketMQ跑起来_入门篇【2】

    上一篇讲了如何再控制台将RocketMQ跑起来,本篇讲解,在asp.net mvc种跑起来,含(发布.订阅). 本次将不挨个贴源码,直接展示目录,根据上一篇文章,进行相应的调整即可. 1.新建一个类库 ...

  4. 搭建ruby环境

  5. Arduino 开源库 u8glib2 之 图标显示【原创】

    Arduino 开源库 u8glib2 研究之 图标显示                -----------------关于drawXBM drawXBMP函数使用的研究 因为心血来潮,近来想做一个 ...

  6. 转:C++与JAVA语言区别

    转自:http://club.topsage.com/thread-265349-1-1.html Java并不仅仅是C++语言的一个变种,它们在某些本质问题上有根本的不同: (1)Java比C++程 ...

  7. [最直白版]一步一步教你用VMware Workstation12安装Ubuntu 16.04和VMware Tools的教程

    [最直白版]Win10下一步一步教你用 VMware Workstation12安装Ubuntu 16.04和VMware Tools的教程 安装过程中使用的软件(要保证电脑里面有下列三个东西): 1 ...

  8. Spark算子--join

      join--Transformation类算子 代码示例 result  

  9. nginx.conf文件

    user  www www; worker_processes auto; error_log  /home/wwwlogs/nginx_error.log  crit; pid        /us ...

  10. 求助帖:android开发初期:为什么我在活动二设置的singInstance模式跑到活动三去了???

    求android开发的高手帮我看看这个问题吧: <activity android:name=".SecondActivity" android:label="Th ...