题意:求从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;
}