最短路/线性差分约束Candies POJ - 3159
Posted streamazure
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最短路/线性差分约束Candies POJ - 3159相关的知识,希望对你有一定的参考价值。
Candies POJ - 3159
题意:
给班级小朋友分糖果,要求满足以下条件:给定(m)组关系(A,B,c),表示(B)得到的糖果比(A)得到的不多于(c)个,即(candy[B]-candy[A]≤c),求(1)号小朋友与(N)号小朋友糖果数之差的最大值。
思路:
线性差分约束。对式子(candy[B]-candy[A]≤c)变形得(candy[B]≤candy[A]+c),容易联想到最短路问题中的松弛操作:
if(d[e.from]+e.dis≤d[e.to]) d[e.to]=d[e.from]+e.dis;
虽然不等式符号方向不同,但其内在逻辑是一致的。因为在最短路的松弛操作完成后(即(d[e.to])的值更新后),都满足d[e.to]≤d[e.from]+e.dis
(并且实际上都取等号,这意味着我们总是在取最大的差),因此可以将(candy[i]) ((1≤i≤n))视为第(i)号小朋友与第(1)号小朋友相差的糖果数,再将之抽象为图论中边的权值,就可以将问题归结为图论中的最短路问题。所求问题即求节点1到节点n的最短路。
而题中给定的约束关系,即每条边的起点、终点及权值。
然后因为数据范围比较大,邻接矩阵会TLE,需要链式前向星+堆优化的dijkstra。
bool done[maxn];
int d[maxn];
int head[maxn];
int n, m;
int num = 0;
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (ch < ‘0‘ || ch>‘9‘) { if (ch == ‘-‘)w = -1; ch = getchar(); }
while (ch >= ‘0‘ && ch <= ‘9‘) s = s * 10 + ch - ‘0‘, ch = getchar();
return s * w;
}
struct HeapNode {
int d, u;
bool operator < (const HeapNode& rhs) const {
return d > rhs.d;
}
};
struct Edge {
int next, to;
LL dist;
}edges[maxn*4];
void add_edge(int from, int to, LL dis) {
num++;
edges[num].next = head[from];
edges[num].to = to;
edges[num].dist = dis;
head[from] = num;
}
void dijkstra(int s) {
priority_queue<HeapNode>Q;
for (int i = 0; i <= n; i++) d[i] = INF;
d[s] = 0;
memset(done, 0, sizeof(done));
HeapNode t;
t.u = s;
t.d = 0;
Q.push(t);
//Q.push(HeapNode{ 0, s });
//HeapNode这个名称不要括起来,否则在VS中会有奇怪的报错
while (!Q.empty()) {
HeapNode x = Q.top(); Q.pop();
//d值最小的结点出队
int u = x.u;
//取该结点的起点
if (done[u]) continue;
for (int i = head[u]; i != 0; i = edges[i].next) {
Edge& e = edges[i];
if (d[u] + e.dist < d[e.to]) {
d[e.to] = d[u] + e.dist;
//更新边的终点的d值
t.u = e.to;
t.d = d[e.to];
Q.push(t);
//Q.push(HeapNode{ d[e.to],e.to });
}
}
done[u] = true;
//标记起点为u的所有边均已访问
}
}
int main()
{
// ios::sync_with_stdio(false);
/// int t; cin >> t; while (t--) {
n = read(); m = read();
for (int i = 1; i <= m; i++) {
int u, v, dis;
u = read(); v = read(); dis = read();
add_edge(u, v, dis);
//b-a<=c 即 a到b的权值为c的单向边
}
dijkstra(1);
cout << d[n];
// }
return 0;
}
以上是关于最短路/线性差分约束Candies POJ - 3159的主要内容,如果未能解决你的问题,请参考以下文章
[poj3159]Candies(差分约束+链式前向星dijkstra模板)