题意:有n-1的站点和原点,然后原点有n-1个人要分别走到所有的站点
然后再从这些站点走回来 问最少总共要走多少路
解法:首先是要走出去 这个很简单就是裸的最短路,然后走完最短路以后要从这些点走回来,我们要考虑到
把所有的边反向,这样一来,又变成了从原点走到所有的点 那么再跑一次最短路就可以得到答案了
#include<queue>
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 1111111
#define inf 0x3f3f3f3f
struct edge{
int v,w,next;
edge(int v,int w,int next):v(v),w(w),next(next){}
edge(){}
}e[1111111];
int st,en,n,m;
int dis[maxn],vis[maxn],head[maxn],a[maxn],in[maxn];
int cnt=0;
void init(){
cnt=0;
st=1;en=n;
memset(head,-1,sizeof head);
}
void add(int u,int v,int w){
e[cnt]=edge(v,w,head[u]);
head[u]=cnt++;
}
int spfa()
{
for(int i=st;i<=en;++i)in[i]=0,vis[i]=0,dis[i]=inf;
queue<int>q;
q.push(st);
dis[st]=0;vis[st]=1;
int u,v;
while(!q.empty())
{
u=q.front();q.pop();vis[u]=0;
// printf("u:%d head:%d\n",u,head[u]);
if(++in[u]>n)return 0;
for(int i=head[u];i!=-1;i=e[i].next){
v=e[i].v;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
if(!vis[v]){
q.push(v);
vis[v]=1;
}
}
}
}
return 1;
}
int from[maxn],to[maxn],va[maxn];
int main()
{
int _;scanf("%d",&_);
while(_--){
scanf("%d%d",&n,&m);
init();
for(int i=0;i<m;++i){
scanf("%d%d%d",&from[i],&to[i],&va[i]);
add(from[i],to[i],va[i]);
}
spfa();
int sum=0;
for(int i=1;i<=n;++i)sum+=dis[i];
init();
for(int i=0;i<m;++i)add(to[i],from[i],va[i]);
spfa();
for(int i=1;i<=n;++i)sum+=dis[i];
printf("%d\n",sum);
}
return 0;
}