POJ 3169 Layout (差分约束系统)

题目链接

题目大意:

一共有n头牛,有ml个关系好的牛的信息,有md个关系不好的牛的信息,对应输入的第一行的三个元素,接下来ml行,每行三个元素A,B,D,表示A牛和B牛相距不希望超过D,接下来md行,每行三个元素A,B,D表示A牛和B牛的相距至少要有D才行。求1号牛和n号牛的最大距离,如果距离无限大输出-2,如果无解输出-1。

思路1

思路2


思路1:

首先考虑吧,求的是1到n的最大距离,即

d[n] - d[1] <= t

可以看作以1为起点n为终点,移项得

d[n] <= d[1] + t

正好就是最短路中松弛过后的不等式的样子,因此相当于求1到n的最短路

简单多了,根据题目信息,有以下内容

a - b <= D
c - d >= D

转换为

a <= b + D
d <= c - D

这样转换是因为上面分析的思路是求解最短路,所以要转化成最短路的不等式,即

if(d[v] > d[u] + w(u, v)){
    d[v] = d[u] + w[u, v];
}

松弛操作前:
d[v] > d[u] + w(u, v)

松弛操作后:
d[v] <= d[u] + w(u, v)

转换后,就可以建边了,分别是,b - > a 权值为 D 和 c - > d 权值为 -D的两个边

建好后以1为源点求最短路即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 51000;
int n, ml, md;
int head[N], nex[N], to[N], edge[N];
int cnt;
int c[N];
bool v[N];
int d[N];
struct SPFA {
	SPFA() {
		mem(head, -1);
		mem(nex, -1);
		mem(c, 0);
		mem(v, 0);
		cnt = 0;
		mem(d, 0x3f);
	}
	void init() {
		SPFA();
	}
	void add(int a, int b, int c) {
		++cnt;
		to[cnt] = b;
		edge[cnt] = c;
		nex[cnt] = head[a];
		head[a] = cnt;
	}
	int spfa(int begin, int end) {
		d[begin] = 0;
		c[begin]++;
		v[begin] = 1;
		queue<int> q;
		q.push(begin);
		bool f = true;
		while (!q.empty()) {
			int t = q.front();
			q.pop();
			if (c[t] > n) {
				f = 0;
				break;
			}
			c[t]++;
			v[t] = 0;
			for (int i = head[t]; i != -1; i = nex[i]) {
				int y = to[i];
				int dist = edge[i];
				if (d[y] > d[t] + dist) {
					d[y] = d[t] + dist;
					if (!v[y]) {
						v[y] = 1;
						q.push(y);
					}
				}
			}
		}
		if (f) {
			return d[end];
		}
		else return -404;
	}
}sp;
int main()
{
	ios::sync_with_stdio(0);
	while (cin >> n >> ml >> md) {
		sp.init();
		for (int i = 0; i < ml; i++) {
			int a, b, c;
			cin >> a >> b >> c;
			sp.add(a, b, c);
		}
		for (int i = 0; i < md; i++) {
			int a, b, c;
			cin >> a >> b >> c;
			sp.add(b, a, -c);
		}
		int res = sp.spfa(1, n);
		if (res == inf) {
			cout << "-2\n";
		}
		else if (res == -404) {
			cout << "-1\n";
		}
		else cout << res << "\n";
	}
	return 0;
}

思路2:

当然,也可以用最长路求解,第二个思路来说说最长路的解法

既然是1到n的最大距离,可以表示为

d[n] - d[1] <= t

转换为

d[1] - d[n] >= -t

进一步化为

d[1] >= d[n] - t

这是符合最长路求解中的松弛操作后的不等式

我们求的还是 t ,也就是说可以求 从n到1的最长路,我们求出来的结果是 -t (注意:是负的),只需要把 n 到 1 的最长路取相反数即可。

接下来就是和上面差不多的过程,建边的时候建立符合最长路松弛操作后的边,就不再赘述了,如果感兴趣可参阅上面尝试写一下,我就直接贴代码了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 51000;
int n, ml, md;
int head[N], nex[N], to[N], edge[N];
int cnt;
int c[N];
bool v[N];
int d[N];
struct SPFA {
	SPFA() {
		mem(head, -1);
		mem(nex, -1);
		mem(c, 0);
		mem(v, 0);
		cnt = 0;
		mem(d, 0x3f);
		for (int i = 0; i < N; i++)d[i] = -d[i];
	}
	void init() {
		SPFA();
	}
	void add(int a, int b, int c) {
		++cnt;
		to[cnt] = b;
		edge[cnt] = c;
		nex[cnt] = head[a];
		head[a] = cnt;
	}
	int spfa(int begin, int end) {
		d[begin] = 0;
		c[begin]++;
		v[begin] = 1;
		queue<int> q;
		q.push(begin);
		bool f = true;
		while (!q.empty()) {
			int t = q.front();
			q.pop();
			if (c[t] > n) {
				f = 0;
				break;
			}
			c[t]++;
			v[t] = 0;
			for (int i = head[t]; i != -1; i = nex[i]) {
				int y = to[i];
				int dist = edge[i];
				if (d[y] < d[t] + dist) {
					d[y] = d[t] + dist;
					if (!v[y]) {
						v[y] = 1;
						q.push(y);
					}
				}
			}
		}
		if (f) {
			return d[end];
		}
		else return -404;
	}
}sp;
int main()
{
	ios::sync_with_stdio(0);
	while (cin >> n >> ml >> md) {
		sp.init();
		for (int i = 0; i < ml; i++) {
			int a, b, c;
			cin >> a >> b >> c;
			sp.add(b, a, -c);
		}
		for (int i = 0; i < md; i++) {
			int a, b, c;
			cin >> a >> b >> c;
			sp.add(a, b, c);
		}
		int res = sp.spfa(n, 1);
		if (res == -inf) {
			cout << "-2\n";
		}
		else if (res == -404) {
			cout << "-1\n";
		}
		else cout << -res << "\n";
	}
	return 0;
}
发布了143 篇原创文章 · 获赞 11 · 访问量 8185

猜你喜欢

转载自blog.csdn.net/weixin_43701790/article/details/104062754