题目描述
有一个邮递员要送东西,邮局在节点 1。他总共要送 n−1 样东西,其目的地分别是节点 2 到节点 n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n−1样东西并且最终回到邮局最少需要的时间。
输入格式
第一行包括两个整数,n 和 m,表示城市的节点数量和道路数量。
第二行到第 (m+1)行,每行三个整数,u,v,w,表示从 u 到 v 有一条通过时间为 w 的道路。
输出格式
输出仅一行,包含一个整数,为最少需要的时间。
输入输出样例
输入 #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% 的数据,1≤n≤200。
对于 100% 的数据,1≤n≤1000,1≤m≤100000,1≤u,v≤n,1≤w≤100000,输入保证任意两点都能互相到达。
题目说明了道路是单行的,说明是有向图,所以每次回来跟去的时候不是同一条路径,所得时间也就不相同
这个题主要就是一次一对多+一次多对一 在返回时是多对一,使用逆向图将其变为一对多
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;
}