poj 3159 candies (差分约束)

题目链接

题目大意:

有若干糖果,n个人,m个条件,每个条件有一行,a,b,c,表示 a 认为 b 的糖果不能比 a 多的多余 c 个,即 

b - a <= c

典型的差分约束问题

差分约束是什么??

差分约束是用于求解一组形如以下的不等式的方法

a - b <= t1
b - d <= t2
a - c <= t3
d - c <= t4
...

差分约束会有若干个约束条件,每一个约束条件由两个变量做差构成

可以将a - b <= t1移项得到,a <= b + t1,这个就是我们在最短路径算法里面经常用到的三角形不等式,在最短路中的形式是如下的

dist[a] <= dist[b] + c;

如果源点到 a 的距离不能通过任何一个点中转来减小,说明是最短路,在上述方程中,明显可以得到的是有一条 b -> a的边,权值为c,(不能确定是否是双向的,因此当作单向考虑),因此可以将每一个约束条件抽象成一条边,构成一个有向图,通过最短路径的方式求得的 dist[ i ]就是一组特解,显然对于每一个 d[ i ] 加上相同的值 A 约束条件依然成立

重点:

如果求x3 - x1的最大值,就可以将上述要求化成x3 - x1 <= t,求 t 的值,而x3 <= x1 + t是最短路中的松弛操作,相当于求x1 到 x3的最短路径,反之,如果求最小值,就是x3 - x1 >= t,相当于x3 >= x1 + t,相当于从x1 到 x3的最长路。

同理,也可以将最大值理解为,x3 - x1 <= t  --> x1 - x3 >= -t,即x3 到 x1的最长路,但是这样求出来的是 -t,我们要求 t ,所以求其相反数即可

本题目直接手打邻接表,然后将约束条件构成一个有向图,通过堆优化的dijkstra求最短路即可

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <iostream>
using namespace std;
const int maxn = 1500010;
int head[maxn], nex[maxn], n, m, d[maxn];
bool v[maxn];
struct p{
	int pos, dist;
	p(){}
	p(int pos, int dist){this->dist = dist;this->pos = pos;}
	bool operator < (const p &a)const{return this->dist > a.dist;}
} node[maxn];
priority_queue<p> q;
void dijkstra(){
	d[1] = 0;
	q.push(p(1, 0)); 
	while (!q.empty()){
		p t = q.top();
		q.pop();
		if(v[t.pos])continue;
		v[t.pos] = true;
		for (int i = head[t.pos]; i >= 0; i = nex[i]){
			if(!v[node[i].pos] && d[node[i].pos] > d[t.pos] + node[i].dist){
				d[node[i].pos] = d[t.pos] + node[i].dist;
				q.push(p(node[i].pos, d[node[i].pos]));
			}
		}
	}
}
int main()
{
//	freopen("in.in", "r", stdin);
	scanf("%d %d", &n, &m);
	memset(d, 0x3f, sizeof d);
	memset(nex, -1, sizeof nex);
	memset(head, -1, sizeof head);
	memset(v, false, sizeof v);
	for (int i = 1; i <= m; i++){
		int a, b, c;scanf("%d %d %d", &a, &b, &c);
		//a -> b
		node[i].pos = b;
		node[i].dist = c;
		nex[i] = head[a];
		head[a] = i;
	}
	dijkstra();
	printf("%d\n", d[n]);
	return 0;
}

 

posted @ 2019-08-21 21:39  correct  阅读(138)  评论(0)    收藏  举报