题意:要求1号点到各点的最短路之和,然后再求各点到1号点的最短路之和。
SPFA邻接表存储
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int N = 10000010, M = 10000010;
int head[N], ver[M], edge[M], Next[M], d[N], vis[N];
int xx[N], yy[N], zz[N];
int n, m, tot;
queue<int> q;
bool v[N];
void add(int x, int y, int z) {
ver[++tot] = y, edge[tot] = z, Next[tot] = head[x], head[x] = tot;
}
bool spfa(int s) {
memset(d, 0x4f, sizeof d);
memset(v, 0, sizeof v);
memset(vis, 0, sizeof vis);
while(!q.empty())
q.pop();
d[s] = 0;
v[s] = 1;
q.push(s);
while(q.size()) {
int x = q.front();
q.pop();
v[x] = 0;
for(int i = head[x]; i; i = Next[i]) {
int y = ver[i], z = edge[i];
if(d[y] > d[x] + z) {
d[y] = d[x] + z;
if(!v[y]) {
q.push(y), v[y] = 1;
vis[y]++;
if(vis[y] >= n)
return false;
}
}
}
}
return true;
}
int main() {
int T;
cin >> T;
while(T--) {
memset(head, 0, sizeof head);
memset(ver, 0, sizeof ver);
memset(edge, 0, sizeof edge);
memset(Next, 0, sizeof Next);
tot = 0;
cin >> n >> m;
long long ans = 0;
for(int i = 1; i <= m; i++) {
scanf("%d%d%d", &xx[i], &yy[i], &zz[i]);
add(xx[i], yy[i], zz[i]);
}
spfa(1);
for(int i = 2; i <= n; i++)
ans += d[i];
memset(head, 0, sizeof head);
memset(ver, 0, sizeof ver);
memset(edge, 0, sizeof edge);
memset(Next, 0, sizeof Next);
tot = 0;
for(int i = 1; i <= m; i++) {
if(xx[i] == 1 && yy[i] == 1)
continue;
if(xx[i] == 1) {
add(yy[i], 0, zz[i]);
continue;
}
if(yy[i] == 1) {
add(0, xx[i], zz[i]);
continue;
}
add(yy[i], xx[i], zz[i]);
}
spfa(0);
for(int i = 2; i <= n; i++)
ans += d[i];
cout << ans << endl;
}
return 0;
}