最短路/线性差分约束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模板)

POJ 3159 Candies(差分约束+spfa+链式前向星)

Candies POJ - 3159 差分约束

Layout POJ - 3169(差分约束+最短路)

Candies---hdu3159(spfa+差分约束)

POJ 3169 Layout (差分约束入门)