题目描述
有一个邮递员要送东西,邮局在节点 111。他总共要送 n−1n-1n−1 样东西,其目的地分别是节点 222 到节点 nnn。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 mmm 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n−1n-1n−1 样东西并且最终回到邮局最少需要的时间。
输入格式
第一行包括两个整数,nnn 和 mmm,表示城市的节点数量和道路数量。
第二行到第 (m+1)(m+1)(m+1) 行,每行三个整数,u,v,wu,v,wu,v,w,表示从 uuu 到 vvv 有一条通过时间为 www 的道路。
输出格式
输出仅一行,包含一个整数,为最少需要的时间。
输入输出样例
输入 #1
输出 #1
83
说明/提示
对于 30%30\%30% 的数据,1≤n≤2001 \leq n \leq 2001≤n≤200。
对于 100%100\%100% 的数据,1≤n≤1031 \leq n \leq 10^31≤n≤103,1≤m≤1051 \leq m \leq 10^51≤m≤105,1≤u,v≤n1\leq u,v \leq n1≤u,v≤n,1≤w≤1041 \leq w \leq 10^41≤w≤104,输入保证任意两点都能互相到达。
题目说明了道路是单行的,说明是有向图,所以每次回来跟去的时候不是同一条路径,所得时间也就不相同
这个题主要就是一次一对多+一次多对一 在返回时是多对一,使用逆向图将其变为一对多
ACcode:
/*
这个题主要就是一次一对多+一次多对一
在返回时是多对一,使用逆向图将其变为一对多
*/
#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
int n , m , sum ;
int dis[1005] , e[1005][1005] , ee[1005][1005] ; //dis距离数组 e存图 ee逆向存图
void dijkstra(int mp[][1005])
{
int vis[1005]={0}; //访问数组 未访问为0
for(int i=1;i<=n;i++)
{
int u=-1 , min_dis=inf;
for(int j=1;j<=n;j++)
{
if( !vis[j] && min_dis > dis[j] ) //找到两个相邻点中最短的路径下标
{
u=j;
min_dis = dis[j];
}
}
if(u==-1) return ;
vis[u]=1;//在下面会对下标为u的点选择最短路径
for(int v=1;v<=n;v++)
{
if( !vis[v] ) //只考虑未访问的点 好狗不吃回头草
dis[v] = min( dis[v] , dis[u] + mp[u][v]); //松弛操作
}
}
}
int main()
{
cin>>n>>m;
fill(e[0],e[0]+1005*1005,inf); //初始化
fill(ee[0],ee[0]+1005*1005,inf); //初始化
fill(dis,dis+1005,inf); //初始化
dis[1]=0; //起点距离为0
for(int i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
e[u][v]=min(w,e[u][v]); //使用min防止重复输入,取重复输入的最小值
//事实上,这题给出的样例全都有重复输入
ee[v][u]=min(w,ee[v][u]); //存一个逆向图
}
dijkstra(e);
for(int i=2;i<=n;i++) sum+=dis[i];
fill(dis,dis+1005,inf); //重新初始化距离数组
dis[1]=0; //初始化起点
dijkstra(ee);
for(int i=2;i<=n;i++) sum+=dis[i];
cout<<sum;
return 0;
}