题解 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;
}
posted @ 2022-11-10 16:00  caijianhong  阅读(11)  评论(0编辑  收藏  举报