P1629 邮递员送信

发布于:2024-03-29 ⋅ 阅读:(14) ⋅ 点赞:(0)

题目描述

有一个邮递员要送东西,邮局在节点 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);
}

本文含有隐藏内容,请 开通VIP 后查看