Invitation Cards POJ - 1511
思路:建两张图,一张正向一张反向,先在正向图里求一遍一号点到所有点的距离,再在反向图里求一遍,反向图里一号点到所有点的距离的意思是所有点到1号点的最短距离,最后相加和就是答案
具体代码如下
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
#include<vector>
#define x first
#define y second
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;
const int N = 1e6 + 10;
int n, m;
LL h1[N], e1[N], w1[N], ne1[N], idx1;
LL h2[N], e2[N], w2[N], ne2[N], idx2;
LL dis1[N], dis2[N];
bool st[N];
void add1(int a, int b, int c){
e1[idx1] = b, w1[idx1] = c, ne1[idx1] = h1[a], h1[a] = idx1++;
}
void add2(int a, int b, int c){
e2[idx2] = b, w2[idx2] = c, ne2[idx2] = h2[a], h2[a] = idx2++;
}
void dijkstra1(){
memset(st, 0, sizeof st);
memset(dis1, 0x3f, sizeof dis1);
dis1[1] = 0;
priority_queue<PLL, vector<PLL>, greater<PLL> >heap;
heap.push({0, 1});
while(heap.size()){
PLL t = heap.top();
heap.pop();
LL ver = t.y;
if(st[ver]) continue;
st[ver] = true;
for(LL i=h1[ver]; i!=-1; i=ne1[i]){
LL j = e1[i];
if(dis1[j] > dis1[ver] + w1[i]){
dis1[j] = dis1[ver] + w1[i];
heap.push({dis1[j], j});
}
}
}
}
void dijkstra2(){
memset(st, 0, sizeof st);
memset(dis2, 0x3f, sizeof dis2);
dis2[1] = 0;
priority_queue<PLL, vector<PLL>, greater<PLL> >heap;
heap.push({0, 1});
while(heap.size()){
PLL t = heap.top();
heap.pop();
LL ver = t.y;
if(st[ver]) continue;
st[ver] = true;
for(LL i=h2[ver]; i!=-1; i=ne2[i]){
LL j = e2[i];
if(dis2[j] > dis2[ver] + w2[i]){
dis2[j] = dis2[ver] + w2[i];
heap.push({dis2[j], j});
}
}
}
}
int main(){
int T;
scanf("%d", &T);
while(T--){
memset(h1, -1, sizeof h1);
memset(h2, -1, sizeof h2);
scanf("%d%d", &n, &m);
while(m--){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add1(a, b, c);
add2(b, a, c);
}
dijkstra1();
dijkstra2();
LL res = 0;
for(int i=2; i<=n; ++i) res += dis1[i] + dis2[i];
printf("%lld\n", res);
}
return 0;
}