题意:就是要你求出所有最短路径上的边之和,然后把结果乘以2
思路:spfa上有一个定理:对于给定的一条边,如果从源点到该边起点的最短距离+起点到该边的最短距离+该边的权值=最短距离,那么说明该边是最短路上的边!
转自:http://blog.csdn.net/u012313382/article/details/47400247
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 10005;
const int maxm = 600000;
const int INF = 0x3f3f3f3f;
int n, m;
struct ee{
int to;
int nxt;
int w;
}edge[maxm];
int head[maxn], tol;
void init(){
memset(head, -1, sizeof head );
tol = 0;
}
void add(int u, int v, int w){
edge[tol].to = v;
edge[tol].w = w;
edge[tol].nxt = head[u];
head[u] = tol++;
}
int d1[maxn], d2[maxn];
bool vis[maxn];
void spfa(int s, int t, int d[])
{
for(int i=0; i<n; ++i) d[i] = INF;
memset(vis, false, sizeof vis );
queue<int> q;
q.push(s);
d[s] = 0;
vis[s] = true;
while(!q.empty()){
int u = q.front(); q.pop();
vis[u] = false;
for(int i=head[u]; ~i; i=edge[i].nxt){
int &v = edge[i].to;
int &cost = edge[i].w;
if(d[v] > d[u] + cost){
d[v] = d[u] + cost;
if(!vis[v]){
vis[v] = true;
q.push(v);
}
}
}
}
}
void solve()
{
int s = 0, t = n-1;
spfa(s, t, d1);
spfa(t, s, d2);
ll ans = 0;
int minn = d1[t];
for(int u=0;u<n;u++)
{
for(int i=head[u];~i;i=edge[i].nxt)
{
int &v=edge[i].to;
int &cost=edge[i].w;
if(d1[u]+d2[v]+cost==minn)
{
ans+=cost;
}
}
}
printf("%I64d\n", ans*2);
}
int main(){
int u, v, l;
while(~scanf("%d%d", &n, &m))
{
init();
for(int i=0; i<m; ++i){
scanf("%d%d%d", &u, &v, &l);
add(u, v, l);
add(v, u, l);
}
solve();
}
return 0;
}