题目描述
有一个邮递员要送东西,邮局在节点 1。他总共要送 n−1 样东西,其目的地分别是节点 2 到节点 n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n−1 样东西并且最终回到邮局最少需要的时间。
输入格式
第一行包括两个整数,n 和 m,表示城市的节点数量和道路数量。
第二行到第 (m+1) 行,每行三个整数,u,v,w 表示从 u 到 v 有一条通过时间为 w 的道路。
输出格式
输出仅一行,包含一个整数,为最少需要的时间。
输入输出样例
输入
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
输出
83
这一看就是用单源最短路径求解答案,首先去第2到n个节点就不用说了,就是1到每个点的最短路径,这个在单元最短路里面讲过,接着就要看走回来这个问题
走回来怎么弄,以2到n每个点为根据点求出最短路径?这样肯定不行,TLE等着你
那怎么弄,其实仔细想一想,就不难想到,我们可以把有向图反过来存,还是以1为基础求单元最短路,dis里面存的就是2到n距离1的最短路了
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e3+5;
int n,m;
struct node{int to,dis;friend bool operator <(node a,node b){return a.dis>b.dis;}
};
vector<node> a[N];
vector<node> b[N];
int dis[N];
int dis2[N];
int vis[N];
int vis2[N];
int s;
priority_queue<node>q1;
priority_queue<node>q2;
void dij_start(){for(int i=1;i<=n;i++)dis[i]=INT_MAX;dis[s]=0;q1.push(node{s,0});while(!q1.empty()){node t=q1.top();q1.pop();int x=t.to;if(vis[x]==1)continue;vis[x]=1;for(int i=0;i<a[x].size();i++){int y=a[x][i].to;int z=a[x][i].dis;dis[y]=min(dis[y],dis[x]+z);if(vis[y]==0)q1.push(node{y,dis[y]});}}
}
void dij_over(){for(int i=1;i<=n;i++)dis2[i]=INT_MAX;dis2[s]=0;q2.push(node{s,0});while(!q2.empty()){node t=q2.top();q2.pop();int x=t.to;if(vis2[x]==1)continue;vis2[x]=1;for(int i=0;i<b[x].size();i++){int y=b[x][i].to;int z=b[x][i].dis;dis2[y]=min(dis2[y],dis2[x]+z);if(vis2[y]==0)q2.push(node{y,dis2[y]});}}
}
signed main(){scanf("%lld%lld",&n,&m);int u,v,w;for(int i=1;i<=m;i++){scanf("%lld%lld%lld",&u,&v,&w);a[u].push_back(node{v,w});b[v].push_back(node{u,w});}s=1;dij_start();dij_over();int sum=0;for(int i=2;i<=n;i++)sum+=dis[i]+dis2[i];printf("%lld",sum);
}