P1260 【工程规划】

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

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

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

\(i-j \leq b\)

\(-j \leq b-i\)

\(j \geq i-b\)

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

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

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

\(\begin{cases}x\leq10\\x\leq5\\\end{cases}\)\(\begin{cases}y\geq10\\y\geq5\\\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\n",d[i]);
	}
	return 0;
}

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

posted @ 2020-07-28 09:07  Poetic_Rain  阅读(64)  评论(0编辑  收藏  举报