码迷,mamicode.com
首页 > 其他好文 > 详细

【最短路/线性差分约束】Candies POJ - 3159

时间:2020-07-29 10:05:28      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:否则   get   因此   str   als   起点   return   die   push   

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

标签:否则   get   因此   str   als   起点   return   die   push   

原文地址:https://www.cnblogs.com/streamazure/p/13394487.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!