• POJ 1511 Invitation Cards(链式前向星,dij,反向建边)


    题目链接

    题目大意

      给(n)个点和(m)条单向边,求从(1)号出发再从(1)号点回来的最短路。

    具体实现

      从(1)号点出发到各个点就是裸的最短路,而从各个点回到(1)号点,可以反向建边求(1)号点到各个点的最短路。但是这题用(vector)存边会卡常数,建议用邻接表(or)链式前向星。

    代码

    const int maxn = 1e6+10;
    struct E {
        int v, w, nxt;
    } e[maxn<<1];
    int n, m, tot, h[maxn], rh[maxn];
    ll d[maxn];
    void add(int a, int b, int c, int h[]) {
        ++tot;
        e[tot].v = b, e[tot].w = c, e[tot].nxt = h[a];
        h[a] = tot;
    }
    ll dij(int h[]) {
        for (int i = 0; i<=n; ++i) d[i] = LLONG_MAX/10;
        d[1] = 0;
        ll res = 0;
        priority_queue<Pii, vector<Pii>, greater<Pii> > pq;
        pq.push(Pii(0,1));
        while(!pq.empty()) {
            Pii t = pq.top(); pq.pop();
            int w = t.first, u = t.second;
            if (d[u]<w) continue;
            res += w;
            for (int i = h[u]; i; i = e[i].nxt) {
                int v = e[i].v;
                if (d[v] > w+e[i].w) {
                    d[v] = w+e[i].w;
                    pq.push(Pii(d[v],v));
                }
            }
        }
        return res;
    }
    int main(void) {
        int t; scanf("%d", &t);
        while(t--) {
            scanf("%d%d", &n, &m);
            for (int i = 0, a, b, c; i<m; ++i) {
                scanf("%d%d%d", &a, &b, &c);
                add(a, b, c, h);
                add(b, a, c, rh);
            }
            ll ans = dij(h); ans += dij(rh);
            printf("%lld
    ", ans);
            for (int i = 0; i<=n; ++i) h[i] = rh[i] = 0;
            tot = 0;
        }
        return 0;
    }
    
  • 相关阅读:
    #include <boost/scoped_ptr.hpp>
    #include <boost/function.hpp>
    #include <boost/bind.hpp>
    8.4散列表查找
    #include <boost/array.hpp>
    异常
    lambda
    #include <amp.h>
    #include <bitset>
    #include <hash_set>
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12750617.html
Copyright © 2020-2023  润新知