zoukankan      html  css  js  c++  java
  • 【最短路/线性差分约束】Candies POJ

    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;
    }
    
  • 相关阅读:
    Windows Server 2008安装Memcached笔记
    解决powerDesinger12逆向工程报错:Unable to list the tables
    冒泡排序算法
    ASP.NET面试题(推荐_有答案)
    ASP.NET服务器控件分类简介
    将excel文件中的数据导入导出至SQL数据库中(Microsoft.Jet.OLEDB.4.0和Microsoft.ACE.OLEDB.12.0|office2003和office2007)
    关于sql access excel以及在web.config中数据库连接字符串的写法
    ODBC / OLEDB___DAO / RDO / ADO
    什么是CSV格式文档
    AppSettings和ConnectionStrings的区别
  • 原文地址:https://www.cnblogs.com/streamazure/p/13394487.html
Copyright © 2011-2022 走看看