传送门
要求出来每个人往返的的路程之和 ,有向图,求起点到各个点来回距离最小和,spfa正向见图,再反向建图,此处的反向建立图,邻接表反向存储就可以了,最后数值太大了,记得用Longlong
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int N =1e6+10,INF=0x3f3f3f3f;
int dist[N],e[N],ne[N],w[N],h1[N],h2[N];
int ee[N],nee[N],ww[N],idx,idx1;
int n,m;
bool st[N];
void add_a(int a,int b,int t){
e[idx]=a,w[idx]=t,ne[idx]=h1[b],h1[b]=idx++;
}
void add_b(int a,int b,int t){
ee[idx1]=b,ww[idx1]=t,nee[idx1]=h2[a],h2[a]=idx1++;
}
void spfa(){
memset(dist,0x3f,sizeof(dist));
memset(st,false,sizeof(st));
queue<int> q;
dist[1]=0;
q.push(1);
st[1]=true;
while(q.size()){
int t=q.front();
q.pop();
st[t]=false;
for(int i=h1[t];i!=-1;i=ne[i]){
int j=e[i];
if(dist[j]>dist[t]+w[i]){
dist[j]=dist[t]+w[i];
if(!st[j]){
st[j]=true;
q.push(j);
}
}
}
}
}
/*
sfpa算法总结:
是bellmam-flody算法的优化
先将头顶点push到队列中
st[确定i是在队列中]=true
while(队列不为空){
1,拿出队列头t,更新st[t]
2,松弛与t相连的边,同时将松弛后的边的,不在
队列中的点加入队列中
}
*/
void spfa1(){
memset(dist,0x3f,sizeof(dist));
memset(st,false,sizeof(st));
dist[1]=0;
queue<int>q;
q.push(1);
st[1]=true;
while(q.size()){
int t =q.front();
q.pop();
st[t]=false;
for(int i=h2[t];i!=-1;i=nee[i]){
int j=ee[i];
if(dist[j]>dist[t]+ww[i]){
dist[j]=dist[t]+ww[i];
if(!st[j]){
st[j]=true;
q.push(j);
}
}
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(h1,-1,sizeof(h1));
scanf("%d%d",&n,&m);
memset(h2,-1,sizeof(h2));
while(m--){
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
add_a(a,b,w);
add_b(a,b,w);
}
long long ans=0;
spfa();
for(int i=1;i<=n;i++)
ans+=dist[i];
spfa1();
for(int i=1;i<=n;i++)
ans+=dist[i];
printf("%lld\n",ans);
}
return 0;
}