邮递员送信(最短路)

邮递员送信
【题目描述】
有一个邮递员要送东西,邮局在结点1。他总共要送N-1样东西,其目的地分别是2-N。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共M条道路,通过每条道路需要一定的时间。这个邮递员每次只能带一样东西。求送完这N-1样东西并且最终回到邮局最少需要多少时间。
【输入文件】
输入文件第一行包括一个正整数N和M;
接下来M行,每行三个正整数U,V,W,表示该条道路为从U到V的,且通过这条道路需要W的时间。满足1<=U,V<=N,1<=W<=10000,输入保证任意两点都能互相到达。
【输出文件】
输出仅一行,包含一个整数,为最少需要的时间。
【样例输入】
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
【数据规模】
对于30%的数据,满足1<=N<=200

对于100%的数据,满足1<=N<=1000,1<=M<=100000


题解:最短路。

因为dijkstra堆优化 的时间复杂度计算错误,上午TLE了- -

dijkstra 堆优化 O((N+M)logN) n为点数,m为边数

SPFA   O(EK) e为边数,k为常数,但是特殊构图会卡成O(N^2)

这道题就是正向见图+反向见图,求两遍以1为起点的单源最短路即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define pa pair<int,int> 
#define N 100003
#define M 1003
#define inf 1000000003
#define LL long long
using namespace std;
int n,m;
int point[N],c[N],v[N],next[N],tot;
int point1[N],c1[N],v1[N],next1[N],tot1;
int dis[M],dis1[M];
void add(int x,int y,int z)
{
	tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; c[tot]=z;
	tot1++; next1[tot1]=point1[y]; point1[y]=tot1; v1[tot1]=x; c1[tot1]=z;
}
void dijkstra(int s)
{
	priority_queue<pa,vector<pa>,greater<pa> > p;
	dis[s]=0; p.push(make_pair(dis[s],s));
	while (!p.empty())
	{
		int now=p.top().second; p.pop();
		for (int i=point[now];i;i=next[i])
		 if (dis[v[i]]>dis[now]+c[i])
		  {
		  	dis[v[i]]=dis[now]+c[i];
		  	p.push(make_pair(dis[v[i]],v[i]));
		  }
	}
}
void dijkstra1(int s)
{
	priority_queue<pa,vector<pa>,greater<pa> > p;
	dis1[s]=0; p.push(make_pair(dis1[s],s));
	while (!p.empty())
	{
		int now=p.top().second; p.pop();
		for (int i=point1[now];i;i=next1[i])
		 if (dis1[v1[i]]>dis1[now]+c1[i])
		  {
		  	dis1[v1[i]]=dis1[now]+c1[i];
		  	p.push(make_pair(dis1[v1[i]],v1[i]));
		  }
	}
}
int main()
{
	freopen("post.in","r",stdin);
	freopen("post.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
	}
	for (int i=1;i<=n;i++)
	 dis[i]=dis1[i]=inf;
	dijkstra(1);
	dijkstra1(1);
	LL ans=0;
	for (int i=2;i<=n;i++)
	 ans+=(LL)dis[i]+(LL)dis1[i];
	printf("%I64d\n",ans);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值