题面

Link

题目背景

小X来到了山区,领略山林之乐。在他乐以忘忧之时,他突然发现,开学迫在眉睫

题目描述

山区有 \(n\) 座山。山之间有 \(m\) 条羊肠小道,每条连接两座山,只能单向通过,并会耗费小X一定时间。

小X现在在 \(1\) 号山,他的目的是 \(n\) 号山,因为那里有火车站。

然而小X的体力是有限的。他每通过一条羊肠小道,就会变得更疲劳,导致他通过任意一条羊肠小道的时间都增加 \(1\)。

输入格式

第一行两个数,\(n\),\(m\)

第 \(2\) 行到第 \(m+1\) 行,每行 \(3\) 个数 \(A\),\(B\),\(C\),表示 \(A\)、\(B\) 之间有一条羊肠小道,可以让小X花费 \(C\) 的时间从 \(A\) 移动到 \(B\)

输出格式

两行 第一行一个数 \(T\),表示小X需要的最短时间

第二行若干个数,用空格隔开,表示小X的移动路线

例:1 4 2 5表示:小X从1号山开始,移动到4号山,再到2号山,最后到5号山。

输入输出样例

输入 #1

5 8

2 4 2

5 2 1

1 2 1

4 3 2

1 3 3

4 5 2

1 5 8

3 5 3

输出 #1

7

1 3 5

说明/提示

n<=10000, m<=200000

数据保证没有多条最短路径

题解

本来以为这道题是道水题,能一遍过的。

结果没想到,这道题太过毒瘤,导致我交了好几遍(雾)

我们的正常思路就是 记录到每个点经过的的边的数量

转移距离时算上 f[t] 来进行更新 。

在从一跑一遍最短路,统计答案就记一下每个点的前驱,就完事了。

核心代码长这样


void spfa()
{
queue<int> q;
memset(dis,127,sizeof(dis));//dis初值设为极大值
q.push(1); dis[1] = 0; vis[1] = 1;
while(!q.empty())
{
int t = q.front(); q.pop(); vis[t] = 0;
for(int i = head[t]; i; i = e[i].net)
{
int to = e[i].to;
int tmp = f[t] + 1;
if(dis[to] > dis[t] + e[i].w + f[t])//算上累计的疲劳度
{
dis[to] = dis[t] + e[i].w + f[t];
f[to] = f[t] + 1;//更新一下 f[to]
pre[to] = t;//记录前驱
if(!vis[to])
{
q.push(to);
vis[to] = 1;
}
}
}
}
}

当你满怀信心交上去时,却发现最后两个点 WA 了。

我想了想,看了看别人的帖子,发现有一组 hack 数据

hack1:
INPUT:
7 7
1 2 2
2 3 2
3 4 2
4 5 2
5 6 2
6 7 2
1 4 10
OUTPUT:
22
1 4 5 6 7 hack2:
INPUT:
7 7
1 2 1
2 3 1
3 4 1
4 5 1
5 6 1
6 7 1
1 5 14
OUTPUT:
19
1 5 6 7

我们把这张图画下来,他张这样

我们问题主要出现在 1-2-3-4-5-6-7 和 1-4-5-6-7 这两条路径,他们的路径长度相同。

但正解却是路径二,因为路径二的疲劳值比 一小。

按照我们正常的做法就会被 HACK 掉。

那我们怎么解决这个问题呢?

这就要用到一个玄学的做法,建反图倒着跑最短路。

证明一下:

假设我们有两条路径 1-2-3-4-5-6-7 和 1-4-5-6-7

当我们更新到 4 的时候,有两条路 到三或者直接到 一。

我们反着跑最短路就会先更新 一,这就避免了上面的那种情况。

这就相当于我们能到终点就直接到终点,而不是走弯路。

Code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int N = 1e5+10;
int n,m,tot,u,v,w,cnt;
int head[N],dis[N],f[N],pre[N],a[N];
bool vis[N];
struct node
{
int to,net,w;
}e[200010];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s =s * 10+ch - '0'; ch = getchar();}
return s * w;
}
void add(int x,int y,int w)
{
e[++tot].w = w;
e[tot].to = y;
e[tot].net = head[x];
head[x] = tot;
}
void spfa()
{
queue<int> q;
memset(dis,127,sizeof(dis));
q.push(n); dis[n] = 0; vis[n] = 1;
while(!q.empty())
{
int t = q.front(); q.pop(); vis[t] = 0;
for(int i = head[t]; i; i = e[i].net)
{
int to = e[i].to;
int tmp = f[t] + 1;
if(dis[to] > dis[t] + e[i].w + f[t])
{
dis[to] = dis[t] + e[i].w + f[t];
f[to] = f[t] + 1;
pre[to] = t;
if(!vis[to])
{
q.push(to);
vis[to] = 1;
}
}
}
}
}
int main()
{
n = read(); m = read();
for(int i = 1; i <= m; i++)
{
u = read(); v = read(); w = read();
add(v,u,w);///建反图跑最短路
}
spfa();
printf("%d\n",dis[1]);
int x = 1;
while(x != n)
{
a[++cnt] = x;
x = pre[x];
}
a[++cnt] = n;
for(int i = 1; i <= cnt; i++)//输出路径
{
printf("%d ",a[i]);
}
return 0;
}

P2832 行路难的更多相关文章

  1. 洛谷P2832 行路难 分析+题解代码【玄学最短路】

    洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座 ...

  2. 洛谷 P2832 行路难

    题面 这个最短路有点special,会有疲劳度的加成效应,这个时候应该怎么办呢? 难就难在,如果走一条路比另一条路长,但是用的边少,那么这条路并不一定就更差. 我们要是能解决这个问题,就可以做出本题. ...

  3. SPFA+寻路(行路难,洛谷2832)

    啊啊啊这道难题总算是做出来了,首先是帅比浮云的题解发出来一下:http://www.cnblogs.com/fuyun-boy/p/5922742.html 原题目地址:https://www.luo ...

  4. [CODEVS2603]公路修建

    题目描述 某国有n个城市,它们互相之间没有公路相通,因此交通十分不便.为解决这一“行路难”的问题,政府决定修建公路.修建公路的任务由各城市共同完成.    修建工程分若干轮完成.在每一轮中,每个城市选 ...

  5. Netty4 学习笔记之三:粘包和拆包

    前言 在上一篇Netty 心跳 demo 中,了解了Netty中的客户端和服务端之间的心跳.这篇就来讲讲Netty中的粘包和拆包以及相应的处理. 名词解释 粘包: 会将消息粘粘起来发送.类似吃米饭,一 ...

  6. P1265 公路修建 最小生成树

    题目描述 某国有n个城市,它们互相之间没有公路相通,因此交通十分不便.为解决这一“行路难”的问题,政府决定修建公路.修建公路的任务由各城市共同完成. 修建工程分若干轮完成.在每一轮中,每个城市选择一个 ...

  7. HTML标记语言

    一.html的文档结构 html含义为超文本标记语言,html文档重要由4个标签来组成就是<html>  <head>  <title>  <body> ...

  8. 洛谷P1265 公路修建(Prim)

    To 洛谷.1265 公路修建 题目描述 某国有n个城市,它们互相之间没有公路相通,因此交通十分不便.为解决这一“行路难”的问题,政府决定修建公路.修建公路的任务由各城市共同完成. 修建工程分若干轮完 ...

  9. 洛谷P1265 公路修建

    P1265 公路修建 177通过 600提交 题目提供者该用户不存在 标签图论 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 long long类型赋值-1为什么… p党80的进 为什么不过 ...

随机推荐

  1. jieba分词-强大的Python 中文分词库

    1. jieba的江湖地位 NLP(自然语言)领域现在可谓是群雄纷争,各种开源组件层出不穷,其中一支不可忽视的力量便是jieba分词,号称要做最好的 Python 中文分词组件. 很多人学习pytho ...

  2. asp image

    @Url.Content("~/Content/images/myimage.png") <img src="~/Content/images/myimage.pn ...

  3. lidar激光雷达领域的分类

    lidar领域可以按分为以下五方面: 激光雷达系统与装备 激光雷达系统与开发 激光雷达光源 激光雷达探测 多光谱激光雷达系统 单光子激光雷达系统 低成本RGB-D距离传感器 激光雷达元器件及装备等 激 ...

  4. F - 丘 (欧拉函数)

    Chinese people think of '8' as the lucky digit. Bob also likes digit '8'. Moreover, Bob has his own ...

  5. Linux服务器被入侵后的处理过程

    突然,频繁收到一组服务器 ping 监控不可达邮件,赶紧登陆 zabbix 监控系统查看流量状况. 可见流量已经达到了 800M 左右,这肯定不正常了,马上尝试 SSH 登陆系统,不幸的事,由于网络堵 ...

  6. Leetcode 974 和可被K整除的子数组

    题目: 解法 //前缀和算法+hash表 class Solution { public: int subarraysDivByK(vector<int>& A, int K) { ...

  7. (高难度SQL)从产品表中找出相同前缀 (都云作者痴 谁解其中味)

    --期盼值 找出AA,3;PDST,3;QPL-,3;TP-,2; --基本表 create table tb_product( id number(9,0) primary key, name nv ...

  8. JS的全局变量无法给Ajax里的变量赋值

    前阶段遇到这么一个问题,在JS定义一个全局变量,JS方法里的其他地方都能使用,偏偏ajax里无法赋值,也不是无法赋值,但赋值总是慢一拍,具体的解决方案如下图所示:

  9. Selenium-WebDriver安装

    一.chrome浏览器: 根据chrome浏览器版本,下载对应的驱动 chromedriver版本 支持的Chrome版本 v2.37 v64-66 v2.36 v63-65 v2.35 v62-64 ...

  10. 第一次编程作业(My Own Score)

    博客班级 https://edu.cnblogs.com/campus/fzzcxy/2018SE2 作业要求 https://edu.cnblogs.com/campus/fzzcxy/2018SE ...