https://www.luogu.org/problem/show?pid=1629
题目描述
有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间。这个邮递员每次只能带一样东西。求送完这N-1样东西并且最终回到邮局最少需要多少时间。
输入输出格式
输入格式:
第一行包括两个整数N和M。
第2到第M+1行,每行三个数字U、V、W,表示从A到B有一条需要W时间的道路。 满足1<=U,V<=N,1<=W<=10000,输入保证任意两点都能互相到达。
【数据规模】
对于30%的数据,有1≤N≤200;
对于100%的数据,有1≤N≤1000,1≤M≤100000。
输出格式:
输出仅一行,包含一个整数,为最少需要的时间。
输入输出样例
输入样例#1:
5 10 2 3 5 1 5 5 3 5 6 1 2 8 1 3 8 5 3 4 4 1 8 4 5 3 3 5 6 5 4 2
输出样例#1:
83
正反两边SPFA
1 #include <algorithm> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 6 using namespace std; 7 8 const int N(1000+5); 9 const int M(100005); 10 int n,m; 11 long long ans; 12 int hed[N],had[N],sumedge; 13 struct Edge 14 { 15 int v,next,w; 16 Edge(int v=0,int next=0,int w=0): 17 v(v),next(next),w(w){} 18 }edge[M<<1]; 19 inline void ins(int u,int v,int w,int *head) 20 { 21 edge[++sumedge]=Edge(v,head[u],w); 22 head[u]=sumedge; 23 } 24 25 bool inq[N]; 26 queue<int>que; 27 int dis1[N],dis2[N]; 28 inline void SPFA_1() 29 { 30 memset(dis1,127/3,sizeof(dis1)); 31 dis1[1]=0; que.push(1); inq[1]=1; 32 for(int u,v;!que.empty();) 33 { 34 u=que.front(); que.pop(); inq[u]=0; 35 for(int i=hed[u];i;i=edge[i].next) 36 { 37 v=edge[i].v; 38 if(dis1[v]>dis1[u]+edge[i].w) 39 { 40 dis1[v]=dis1[u]+edge[i].w; 41 if(!inq[v]) inq[v]=1,que.push(v); 42 } 43 } 44 } 45 } 46 inline void SPFA_2() 47 { 48 memset(dis2,127/3,sizeof(dis2)); 49 dis2[1]=0; que.push(1); inq[1]=1; 50 for(int u,v;!que.empty();) 51 { 52 u=que.front(); que.pop(); inq[u]=0; 53 for(int i=had[u];i;i=edge[i].next) 54 { 55 v=edge[i].v; 56 if(dis2[v]>dis2[u]+edge[i].w) 57 { 58 dis2[v]=dis2[u]+edge[i].w; 59 if(!inq[v]) inq[v]=1,que.push(v); 60 } 61 } 62 } 63 } 64 65 int main() 66 { 67 scanf("%d%d",&n,&m); 68 for(int u,v,w,i=1;i<=m;i++) 69 { 70 scanf("%d%d%d",&u,&v,&w); 71 ins(u,v,w,hed);ins(v,u,w,had); 72 } 73 SPFA_1(); SPFA_2(); 74 for(int i=2;i<=n;i++) ans+=(long long)dis1[i]+dis2[i]; 75 printf("%lld ",ans); 76 return 0; 77 }