P1629 邮递员送信

题意:求从1到[2, n]中每一个点的最短路(k_i),再求从[2, n]的每一个点出发到1的最短路(p_i), 求所有(k, p)的和。

堆优化dijkstra (O(nmlogn)):40pts

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>

using namespace std;

const int N = 1010, M = 100010, INF = 0x3f3f3f3f;

int h[N], e[M], ne[M], w[M], idx;
int dist[N], st[N];
int n, m, q;

struct Node{
    int val, idx;
    
    bool operator > (const Node &n) const {
        return val > n.val;
    }
};

priority_queue<Node, vector<Node>, greater<Node>> heap;//小根堆

int dijkstra(int x, int y){
    memset(dist, 0x3f, sizeof dist);
    memset(st, 0, sizeof st);
    dist[x] = 0;
    
    heap.push({0, x});
    
    while(heap.size()){
        int k = heap.top().idx;
        heap.pop();
        if(st[k]) continue;
        st[k] = 1;
        for(int i = h[k]; ~i; i = ne[i]){
            int j = e[i];
            if(dist[j] > dist[k] + w[i]){
                dist[j] = dist[k] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
    
    return dist[y];
}

void add(int a, int b, int v){
    e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}

int main(){
    memset(h, -1, sizeof h);
    
    cin >> n >> m;
    
    while(m --){
        int a, b, v;
        cin >> a >> b >> v;
        
        add(a, b, v);
    }
    
    int res = 0;
    
    for(int i = 2; i <= n; i ++)
        res += dijkstra(1, i) + dijkstra(i, 1);
            
    cout << res;
    
    return 0;
}

建反向图+堆优化dijkstra (O(mlogn))

#include<iostream>
#include<cstring>
#include<queue>
#include<vector>

using namespace std;

const int N = 1010, M = 100010, INF = 0x3f3f3f3f;

int h[N << 1], e[M << 1], ne[M << 1], w[M << 1], idx;
int dist[N << 1], st[N << 1];
int n, m, q;

struct Node{
    int val, idx;
    
    bool operator > (const Node &n) const {
        return val > n.val;
    }
};

priority_queue<Node, vector<Node>, greater<Node>> heap;

void dijkstra(int x){
    dist[x] = 0;
    
    heap.push({0, x});
    
    while(heap.size()){
        int k = heap.top().idx;
        heap.pop();
        if(st[k]) continue;
        st[k] = 1;
        for(int i = h[k]; ~i; i = ne[i]){
            int j = e[i];
            if(dist[j] > dist[k] + w[i]){
                dist[j] = dist[k] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
}

void add(int a, int b, int v){
    e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}

int main(){
    memset(dist, 0x3f, sizeof dist);
    memset(h, -1, sizeof h);
    memset(st, 0, sizeof st);
    
    cin >> n >> m;
    
    while(m --){
        int a, b, v;
        cin >> a >> b >> v;
        
        add(a, b, v);
        add(b + n, a + n, v);
    }
    
    int res = 0;
    
    dijkstra(1);// 1~n原图
    dijkstra(1 + n); // n + 1到2n反向图
    
    for(int i = 1; i <= n << 1; i ++) res += dist[i];
    
    cout << res;
    
    return 0;
}
原文地址:https://www.cnblogs.com/tomori/p/13809840.html