邮递员送信
邮递员送信
题目描述
有一个邮递员要送东西,邮局在节点 1 1 1。他总共要送 n − 1 n-1 n−1 样东西,其目的地分别是节点 2 2 2 到节点 n n n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 m m m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n − 1 n-1 n−1 样东西并且最终回到邮局最少需要的时间。
输入格式
第一行包括两个整数, n n n 和 m m m,表示城市的节点数量和道路数量。
第二行到第 ( m + 1 ) (m+1) (m+1) 行,每行三个整数, u , v , w u,v,w u,v,w,表示从 u u u 到 v v v 有一条通过时间为 w w w 的道路。
输出格式
输出仅一行,包含一个整数,为最少需要的时间。
样例 #1
样例输入 #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
提示
对于 30 % 30\% 30% 的数据, 1 ≤ n ≤ 200 1 \leq n \leq 200 1≤n≤200。
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 3 1 \leq n \leq 10^3 1≤n≤103, 1 ≤ m ≤ 1 0 5 1 \leq m \leq 10^5 1≤m≤105, 1 ≤ u , v ≤ n 1\leq u,v \leq n 1≤u,v≤n, 1 ≤ w ≤ 1 0 4 1 \leq w \leq 10^4 1≤w≤104,输入保证任意两点都能互相到达。
题解以及思路
这个题很明显是一个有向图的最短路的问题,我们可以实现从节点1到其他节点的最短路,那么我们应该如何实现从其他节点到节点1的最短路呢,很显然如果用简单的单源点或者多源点最短路都会超时。
我们可以换一个角度想一想,如何让返回也是一对多的方式呢,就是可以通过节点1就可以更新其他节点到节点1的最短距离,这里我们可以很容易的想到将我们存图的邻接矩阵反过来就可以实现
具体代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
const int M=1e5+10;
const int INF=0x3f3f3f3f;
int n,m;
int dist[N];
bool st[N];
int mp[N][N];
void dijkstra(int x){
memset(dist,INF,sizeof dist);
memset(st,false,sizeof st);
dist[x]=0;
for(int i=0;i<n;i++){
int t=-1;
for(int j=1;j<=n;j++){
if(!st[j]&&(t==-1||dist[j]<dist[t])){
t=j;
}
}
st[t]=true;
for(int j=1;j<=n;j++){
dist[j]=min(dist[j],dist[t]+mp[t][j]);
}
}
}
int main(){
cin>>n>>m;
memset(mp,INF,sizeof mp);
for(int i=1;i<=m;i++){
int a,b,c;
cin>>a>>b>>c;
mp[a][b]=min(mp[a][b],c);
}
dijkstra(1);
int res=0;
sort(dist+2,dist+n+1);
for(int i=2;i<=n;i++){
res+=dist[i];
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
int t=mp[i][j];
mp[i][j]=mp[j][i];
mp[j][i]=t;
}
}
dijkstra(1);
for(int i=2;i<=n;i++){
res+=dist[i];
}
cout<<res<<endl;
return 0;
}