题解 P1260 【工程规划】

观前提示:

建议完成以下题目后在来看此题/题解哦。

P3385 【模板】负环

P5960 【模板】差分约束算法

题目分析:

核心算法:差分约束

(这几乎是一道裸题)


题中写道:

“不等式形如\(T_i-T_j \leq b\)代表\(i\)\(j\)的起始时间必须满足的条件。每个不等式的右边都是一个常数\(b\),这些常数可能不相同,但是它们都在区间\(\left(-100,100 \right)\)内。”

即,符合差分约束算法的定义。

所以我们套用差分约束的模板,可以先求出一个可行解。

与纯模板不同的是,题目中要求:

“对于有解的情况,要使最早进行的那个任务和整个工程的起始时间相同,也就是说,\(T_1,T_2,…,T_n\)中至少有一个为0。”

我们已知:对于所求出的解,存在以下性质:

\(x=\left( x_1,x_2,x_3,...,x_n\right)\)是不等式的一个解。设\(d\)为任意常数,则\(x+d=\left( x_1+d,x_2+d,x_3+d,...,x_n+d\right)\)也是该不等式的一个解。

所以只要在原模板的基础上,找到可行解中的最小值,然后让整体的解减去该值即可。

代码如下:

#include <bits/stdc++.h>
#define MAXN 100000
#define INF 0x3f3f3f3f
using namespace std;
struct EDGE
{
	int to,nxt,val;
}	e[MAXN];
int cnt=0,adj[MAXN],ori=0,vis[MAXN],num[MAXN],dis[MAXN];
int n,m;
void addedge(int u,int v,int w)
{
	e[++cnt].to=v; e[cnt].val=w; e[cnt].nxt=adj[u]; adj[u]=cnt;
}
queue < int > q;
bool SPFA()
{
	for(int i=1;i<=n;++i)	{addedge(0,i,0);dis[i]=INF;}
	q.push(ori); dis[ori]=0; ++num[ori]; vis[ori]=1;
	while(!q.empty())
	{
		int u=q.front(); q.pop();	vis[u]=0;
		for(int i=adj[u];i;i=e[i].nxt)
		{
			int v=e[i].to;	
			if(dis[v]>dis[u]+e[i].val)
			{
				dis[v]=dis[u]+e[i].val;
				if(!vis[v])
				{
					vis[v]=1;	q.push(v);
					++num[v];
					if(num[v]>n)	return 0;
				}
			}
		}
	}
	return 1;
}
int main()
{
	int temp=INF;scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)
	{
		int u,v,w; scanf("%d%d%d",&u,&v,&w);
		addedge(v,u,w);
	}
	if(SPFA())
	{
		for(int i=1;i<=n;++i)
			temp=min(temp,dis[i]);
		for(int i=1;i<=n;++i)
			printf("%d\n",dis[i]-temp);
	}	
	else
		printf("NO SOLUTION");
	return 0;
}
posted @ 2020-10-02 10:30  x_miracle  阅读(99)  评论(0编辑  收藏  举报