P1260 【工程规划】

题目非常得简洁明了,差分约束的裸题,甚至连不等式都给你写出来了

没什么好分析的,直接看不等式建立方程(这里把(Ti)(Tj)都表示为(i)(j)

因为求的应该是最早的开始时间,我们应该转化为(≥),然后跑最长路求解

(i-j leq b)

(-j leq b-i)

(j geq i-b)

那么就应该是从(i)(j)建一条负边权

至于为什么是跑最长路,如果不太理解的话可以看看我的博客

其实我们可以用数学的方法简单地思考一下这个问题

(egin{cases}xleq10\xleq5\end{cases})(egin{cases}ygeq10\ygeq5\end{cases})

我们得出的答案应该是 (x leq 5)(y geq10) (初中数学基本知识),我们应该的正解应该是范围更小的那一个。对于小于等于,最短路会使得答案范围更小;相反,大于等于的话,最长路使得答案范围更小,满足不等式组的求解

那么对于无解的情况,就是通过SPFA判负环就可以了,如果不会的话建议先做这一道题,顺便推荐一下同桌的博客

那么应该就没什么疑问了,直接看代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN=5*1e6+51;
int n,m;
struct node{
	int net,to,w;
}e[MAXN];
int head[MAXN],tot;
void add(int x,int y,int z){
	e[++tot].net=head[x];
	e[tot].to=y;
	e[tot].w=z;
	head[x]=tot;
}
int d[MAXN],vis[MAXN];
bool v[MAXN];
queue<int>q;
bool spfa(int s){
	for(register int i=0;i<=n;i++) d[i]=-20040915;
	d[s]=0,v[s]=true,vis[s]=1;
	q.push(s);
	while(!q.empty()){
		int x=q.front();
		q.pop();
		v[x]=false;
		for(register int i=head[x];i;i=e[i].net){
			int y=e[i].to,z=e[i].w;
			if(d[y]<d[x]+z){
				d[y]=d[x]+z;
				if(v[y]==false){
					v[y]=true;
					vis[y]++;
					if(vis[y]>=n) return false;
					q.push(y);
				}
			}
		}
	} 
	return true;
}
int main(){
	scanf("%d%d",&n,&m);
	for(register int i=1;i<=m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(y,x,z);
	}
	for(register int i=1;i<=n;i++) add(0,i,0);
	if(spfa(0)==false) puts("NO SOLUTION");
	else{
		for(register int i=1;i<=n;i++) printf("%d
",d[i]);
	}
	return 0;
}

如果有错的地方请指出啊,希望对大家有帮助

原文地址:https://www.cnblogs.com/Poetic-Rain/p/13389120.html