题解 P2294【[HNOI2005]狡猾的商人】
problem
是否存在数列 \(a\) 使得它满足形如 \(\sum_{l\leq i\leq r}a_i=x\) 的 \(m\) 个限制?\(n,m\leq 1000\)。
solution
等价于构造出一个前缀和,使得它满足所有形如 \(sum_r-sum_{l-1}=x\) 的限制(其中 \(l,r,x\) 为常数)。差分约束跑最短路。
变形:\(v=r,u=l-1\),则 \(dis_v=dis_u+x\Rightarrow dis_v\leq dis_u+x\land dis_v-x\geq dis_u\)。
有解情况就是它真的构造了一组 \(dis\),无解就是跑出负环,这题 \(n,m\leq 1000\) 直接 BF 都能过才对。
code
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr,##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
typedef long long LL;
template<int N,int M,class T=int> struct graph{
int head[N+10],nxt[M*2+10],cnt;
struct edge{
int u,v; T w;
edge(int u=0,int v=0,T w=0):u(u),v(v),w(w){}
} e[M*2+10];
graph(){memset(head,cnt=0,sizeof head);}
edge&operator[](int i){return e[i];}
void add(int u,int v,T w=0){e[++cnt]=edge(u,v,w),nxt[cnt]=head[u],head[u]=cnt;}
void link(int u,int v,T w=0){add(u,v,w),add(v,u,w);}
};
int n,m,dis[210],app[210];
bool vis[210];
graph<210,2010> g;
bool spfa(int s){
queue<int> q;
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
memset(app,0,sizeof app);
for(q.push(s),dis[s]=0;!q.empty();){
int u=q.front(); q.pop();
vis[u]=0;
for(int i=g.head[u];i;i=g.nxt[i]){
int v=g[i].v;
if(dis[v]>dis[u]+g[i].w){
dis[v]=dis[u]+g[i].w;
if(!vis[v]){
if(++app[v]>=n+2) return 1;
vis[v]=1,q.push(v);
}
}
}
}
return 0;
}
int mian(){
for(int i=1,l,r,w,u,v;i<=m;i++) scanf("%d%d%d",&l,&r,&w),u=l,v=r+1,g.add(u,v,w),g.add(v,u,-w);
for(int i=1;i<=n;i++) g.add(0,i,0);
puts(spfa(0)?"false":"true");
//有负环就造假
return 0;
}
void reset(){
memset(g.head,g.cnt=0,sizeof g.head);
}
int main(){
for(scanf("%*d");~scanf("%d%d",&n,&m);reset(),mian());
return 0;
}
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://www.cnblogs.com/caijianhong/p/solution-p2294.html