P1629邮递员送信

邮递员送信

题目描述

有一个邮递员要送东西,邮局在节点 1 1 1。他总共要送 n − 1 n-1 n1 样东西,其目的地分别是节点 2 2 2 到节点 n n n。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有 m m m 条道路。这个邮递员每次只能带一样东西,并且运送每件物品过后必须返回邮局。求送完这 n − 1 n-1 n1 样东西并且最终回到邮局最少需要的时间。

输入格式

第一行包括两个整数, 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 1n200

对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 3 1 \leq n \leq 10^3 1n103 1 ≤ m ≤ 1 0 5 1 \leq m \leq 10^5 1m105 1 ≤ u , v ≤ n 1\leq u,v \leq n 1u,vn 1 ≤ w ≤ 1 0 4 1 \leq w \leq 10^4 1w104,输入保证任意两点都能互相到达。

#include
using namespace std;
#define pii pair<int,int>
#define il inline
#define re register
const int MAXN=1e5;
int u[MAXN],v[MAXN],w[MAXN];
int dis[MAXN];
int n,m;

//反向建边
il void over()
{
	for(int i=1;i<=m;i++)
		swap(u[i],v[i]);
	return;
}
//

//Bellman Ford
il void Ford()
{
	memset(dis,0x3f3f3f,sizeof(dis));//初始化 
	dis[1]=0;
	for(int k=1;k<n;k++)
		for(int i=1;i<=m;i++)
			dis[v[i]]=min(dis[v[i]],dis[u[i]]+w[i]);
	return;
} 
// 

int main()
{
	int ans=0;
	cin>>n>>m;
	for(int i=1;i<=m;i++)
		cin>>u[i]>>v[i]>>w[i];
	Ford();
	for(int i=1;i<=n;i++) ans+=dis[i];//从一到多 
//	for (int i=1;i<=n;i++) cout<
	over();//反向建图 
	Ford();//再跑一遍 
	for(int i=1;i<=n;i++) ans+=dis[i];//从多到一 
	cout<<ans;
	return 0;
}

ps:

单源最短路问题,用bellman-ford解决,这是一道bellman-ford模板题

bellman-ford:

设 f ( k , i ) 为经过 < = k 条边的情况下 f − k 的最短路 设f(k,i)为经过<=k条边的情况下f-k的最短路 f(k,i)为经过<=k条边的情况下fk的最短路
若存在有向边 ( u , v , w ) ,则用 f ( k , u ) + w 更新 f ( k + 1 , v ) 若存在有向边(u,v,w),则用f(k,u)+w更新f(k+1,v) 若存在有向边(u,v,w),则用f(k,u)+w更新f(k+1,v)
根据题目要求,因为要来回跑,所以反向建图再跑一遍bellman-ford即可

end

你可能感兴趣的:(算法,图论)