[HNOI2005]狡猾的商人
Posted Mrsrz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HNOI2005]狡猾的商人相关的知识,希望对你有一定的参考价值。
题目:洛谷P2294、BZOJ1202。
题目大意:有n个月,m条信息,每条信息告诉你从第u月到第v月(含u和v)的收入是t。问能否满足所有信息。
解题思路:设$s_i$为第i个月的收入,则每条信息就是告诉你$s_v-s_{u-1}=t$。
我们把信息拆分为两条:$s_v-s_{u-1}\leq t$和$s_{u-1}-s_v\leq -t$。
然后就是差分约束。
SPFA判负环即可。
C++ Code:
#include<cstdio> #include<cctype> #include<cstring> #include<iostream> using namespace std; int n,m,cnt,head[155],dis[155]; bool vis[155]; struct edge{ int to,dis,nxt; }e[50000]; bool dfs(int now){ for(int i=head[now];i!=-1;i=e[i].nxt) if(dis[e[i].to]>dis[now]+e[i].dis){ dis[e[i].to]=dis[now]+e[i].dis; if(!vis[e[i].to]){ vis[e[i].to]=true; if(!dfs(e[i].to))return false; vis[e[i].to]=false; }else return false; } return true; } inline int readint(){ char c=getchar(); bool b=false; for(;!isdigit(c);c=getchar())b=c==‘-‘; int d=0; for(;isdigit(c);c=getchar()) d=(d<<3)+(d<<1)+(c^‘0‘); return b?-d:d; } int main(){ ios::sync_with_stdio(false); for(int t=readint();t--;){ memset(head,-1,sizeof head); memset(e,0,sizeof e); cnt=0; n=readint(); for(m=readint();m--;){ int u=readint(),v=readint(),t=readint(); e[++cnt]=(edge){u-1,-t,head[v]}; head[v]=cnt; e[++cnt]=(edge){v,t,head[u-1]}; head[u-1]=cnt; } for(int i=0;i<=n;++i){ e[++cnt]=(edge){i,0,head[n+1]}; head[n+1]=cnt; } memset(dis,0x3f,sizeof dis); memset(vis,0,sizeof vis); dis[n+1]=0; vis[n+1]=true; cout<<boolalpha<<dfs(n+1)<<endl; } return 0; }
以上是关于[HNOI2005]狡猾的商人的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ-1202: [HNOI2005]狡猾的商人 (并查集+前缀和)
bzoj 1202: [HNOI2005]狡猾的商人 并查集好题