zoukankan      html  css  js  c++  java
  • 洛谷 P1629 邮递员送信

    洛谷 P1629 邮递员送信

    题目链接:洛谷 P1629 邮递员送信

    算法标签: 图论最短路

    题目

    题目描述

    有一个邮递员要送东西,邮局在节点1.他总共要送N-1样东西,其目的地分别是2~N。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间。这个邮递员每次只能带一样东西。求送完这N-1样东西并且最终回到邮局最少需要多少时间。

    输入格式

    第一行包括两个整数N和M。

    第2到第M+1行,每行三个数字U、V、W,表示从A到B有一条需要W时间的道路。 满足1<=U,V<=N,1<=W<=10000,输入保证任意两点都能互相到达。

    【数据规模】

    对于30%的数据,有1≤N≤200;

    对于100%的数据,有1≤N≤1000,1≤M≤100000。

    输出格式

    输出仅一行,包含一个整数,为最少需要的时间。

    输入输出样例

    输入 #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
    

    题解:

    这道题可以说很坑了,坑点就在于有向图!!!我们可以发现按照题中描述我们需要从起始点先到某个点,在从某个点回到起始点,反复循环。但是由于是有向图,所以去的时候的最短路不一定就是回来时候的最短路,由于如果求n个点的最短路,或者多源单点最短路,时间上是承受不了的,所以这个问题成为整个题的难点所在,那么怎么处理???

    大致的思路是这样,把我们从起点(邮局)开始的一边最短路定为正向,那么我们回来就相当于一次反向求最短路。

    按照我们正常想法是从N个点向起始点都跑一遍最短路(是不是想起了Floyd),那么加入我们反向建图,这就变成了从起始点向N个重点跑最短路,就又变成了另外一组单源最短路,在时间上是可以接受的。

    因为半死不活的SPFA算法和它(在不稳定方面)极为优秀的时间复杂度,个人放弃了这个算法,所以没有写SPFA的题解(从题目中M的数据范围就放弃了),正常使用堆优化Dijkstra,代码如下:

    AC代码

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1010;
    const int M = 100100;
    
    int n, m, ans, vis[N], dis[N], fvis[N], fdis[N];
    int tot, to[M], nex[M], val[M], head[N];
    int ftot, fto[M], fnex[M], fval[M], fhead[N];
    
    void add(int x, int y, int z)
    {
    	to[ ++ tot] = y;
    	val[tot] = z;
    	nex[tot] = head[x];
    	head[x] = tot;
    	fto[ ++ ftot] = x;
    	fval[ftot] = z;
    	fnex[ftot] = fhead[y];
    	fhead[y] = ftot;
    }
    priority_queue < pair<int, int> > q;
    void dijkstra(int s)
    {
    	memset(dis, 0x3f, sizeof dis);
    	memset(vis, 0, sizeof vis);
    	dis[s] = 0;
    	q.push(make_pair(0, s));
    	while(!q.empty())
    	{
    		int x = q.top().second;
    		q.pop();
    		if (vis[x])
    			continue ;
    		vis[x] = 1;
    		for (int i = head[x]; i; i = nex[i])
    		{
    			if (dis[to[i]] > dis[x] + val[i])
    			{
    				dis[to[i]] = dis[x] + val[i];
    				q.push(make_pair(-dis[to[i]], to[i]));
    			}
    		}
    	}
    }
    void fdijkstra(int s)
    {
    	memset(fdis, 0x3f, sizeof fdis);
    	memset(fvis, 0, sizeof fvis);
    	fdis[s] = 0;
    	q.push(make_pair(0, s));
    	while(!q.empty())
    	{
    		int x = q.top().second;
    		q.pop();
    		if (fvis[x])
    			continue ;
    		fvis[x] = 1;
    		for (int i = fhead[x]; i; i= fnex[i])
    		{
    			if (fdis[fto[i]] > fdis[x] + fval[i])
    			{
    				fdis[fto[i]] = fdis[x] + fval[i];
    				q.push(make_pair(-fdis[fto[i]], fto[i]));
    			}
    		}
    	}
    } 
    int main()
    {
    	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);
    	}
    	dijkstra(1);
    	fdijkstra(1);
    	for (int i = 2; i <= n; i ++ )
    	{
    		ans += dis[i] + fdis[i];
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    python json 和 pickle的补充 hashlib configparser logging
    go 流程语句 if goto for swich
    go array slice map make new操作
    go 基础
    块级元素 行内元素 空元素
    咽炎就医用药(慢性肥厚性咽炎)
    春季感冒是风寒还是风热(转的文章)
    秋季感冒 咳嗽 怎么选药
    解决IE浏览器“无法显示此网页”的问题
    常用的 css 样式 记录
  • 原文地址:https://www.cnblogs.com/littleseven777/p/11842110.html
Copyright © 2011-2022 走看看