POJ 3169 Layout【差分约束+spfa判负环】

POJ 3169 Layout

题目大意:
在一个一维坐标轴上排列各个点,使得每两个点直接满足给定的两种条件
某两点间的距离不大于某个值,以及某两点距离不小于某个值

具体思路:
差分约束,最短路求解
不懂差分约束的,可以参考这篇博客https://blog.csdn.net/whereisherofrom/article/details/78922648
差分约束的条件:
假设标号A

  • B-A<=W => w(A,B)=W
  • B-A>=W => w(B,A)=-W
  • 坐标A <= 坐标B => w(A,B)=0

注意一个坐标可以有多个点

根据差分约束条件建图,然后spfa判负环求最短路,若有负环则输出-1(此处不考虑是否连通图也能ac),无法到达则输出-2,否则输出最短距离,即最大差值。

具体代码:

#include
#include
#include
#include
#include
using namespace std;
int const N = 1000 + 10, M = 2e4 + 10;
int const INF = 0x3f3f3f3f;
int d[N],visit[N],h[N],inq[N];
int n, ml, md, len;
struct Node {
     
	int v, w, next;
}e[M];
void add(int u,int v,int w)
{
     
	e[len].v = v;
	e[len].w = w;
	e[len].next = h[u];
	h[u] = len++;
}
int spfa()
{
     
	memset(visit, 0, sizeof(visit));
	memset(d, 0x3f, sizeof(d));
	memset(inq, 0, sizeof(inq));
	queue<int> q;
	d[1] = 0;
	q.push(1);
	inq[1]++;
	while (q.size())
	{
     
		int t = q.front();
		q.pop();
		visit[t] = 0;
		for (int i = h[t];~i; i=e[i].next)
		{
     
			int v = e[i].v;
			int w = d[t] + e[i].w;
			if (d[v] > w)
			{
     
				d[v] = w;
				if (!visit[v]) {
     
					if (inq[v] > n)return -1;
					q.push(v);
					visit[v] = 1;
					inq[v]++;
				}
			}
		}
	}
	if (d[n] == INF)return -2;
	return d[n];
}
int main()
{
     
	memset(h, -1, sizeof(h));
	scanf("%d%d%d", &n, &ml, &md);
	for (int i = 1; i <= ml; i++) 
	{
     
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		add(u, v, w);	//v-u<=w
	}
	for (int i = 1; i <= md; i++)
	{
     
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		add(v, u, -w);	//v-u>=w
	}
	for (int i = 1; i < n; i++)
		add(i+1, i, 0);	//标号前的点必须排在前面,即Xi<=Xi+1(题意标明,一个坐标可以有多个点)
	printf("%d\n", spfa());
	return 0;
}

你可能感兴趣的:(差分约束,最短路,OJ题解)