洛谷P1260 工程规划

裸的差分约束吧。

对于 \(T_i-T_j≤b\),移项可得 \(T_i≤T_j+b\),所以可以加一条从 \(T_j\)\(T_i\) 长为 \(b\) 的边,再跑一遍最短路,就找到的一组特解。

跑最短路之前,要建一个超级源点,向每一个点连一条边,避免图不连通。

\(dis\) 数组里存的就是特解,然后把 \(dis\) 里最小的找到,输出的时候减去它就行了。

因为有无解的情况,所以要用 \(spfa\) 它没死,判负环,如果有负环,输出 NO SOLUTION

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 1010
#define M 6010

using namespace std;

int n,m;
struct edge
{
	int v,w,nxt;
}e[M];
int head[N],tot;

void add(int u,int v,int w)
{
	e[++tot]=(edge){v,w,head[u]};
	head[u]=tot;
}

int dis[N],flag[N],sum[N];
queue <int> que;

void spfa()
{
	memset(dis,0x3f,sizeof(dis));
	dis[0]=0;
	que.push(0);
	flag[0]=1;
	while(!que.empty())
	{
		int u=que.front();
		que.pop();
		flag[u]=0;
		sum[u]++;
		if(sum[u]>=n)
		{
			puts("NO SOLUTION");
			return;
		}
		for(int i=head[u]; i; i=e[i].nxt)
		{
			int v=e[i].v,w=e[i].w;
			if(dis[u]+w<dis[v])
			{
				dis[v]=dis[u]+w;
				if(!flag[v])
				{
					que.push(v);
					flag[v]=1;
				}
			}
		}
	}
	int mind=0;
	for(int i=1; i<=n; i++) mind=min(mind,dis[i]);
	for(int i=1; i<=n; i++) printf("%d\n",dis[i]-mind);
	return;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1; i<=m; i++)
	{
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(v,u,w);
	}
	for(int i=1; i<=n; i++) add(0,i,0);
	spfa();
	return 0;
}
posted @ 2020-06-20 18:18  Acestar  阅读(122)  评论(0编辑  收藏  举报