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;
}
本文来自博客园,作者:correct,转载请注明原文链接:https://www.cnblogs.com/correct/p/12862055.html

浙公网安备 33010602011771号