链接:https://ac.nowcoder.com/acm/contest/7031/F
来源:牛客网
题目描述
新冠病毒被医生从患者的身体中赶了出来,它很伤心,原本一切都是那么的快乐,它和它的孩子们快乐地生活在一起。但是这里的抗疫力度太强了,被赶出来后,由于人们都带了口罩,它没办法再次回到之前那样的舒适环境。现在它想要离开医院回家。它有很多条路可以离开医院,虽然它想要尽可能快的回去,但是它还想看看路上的其它病毒过得怎么样,也好顺便带它们一起离开,于是它决定走第二短的路回去。医院总有 V (0 ~ V-1) 个路口,这些路口之间有 E 条路连接。新冠病毒现在在第 0 个路口,第 V-1 个路口就是医院出口。保证有路可以离开。 第二短路是严格第二短(小于最短路),保证路径存在,路径可以重复走。
输入描述:
第一行:两个空格隔开的整数 V 和 E 。( 1 <= V <= 5000 ),( 0 <= E <= 100000 ) 。第二行开始有 E 行:每行包含 3 个空格隔开的整数 a、b、d 。表示路口 a 和 b 之间有一条长度为 d 的路。( 0 <= a,b < V ),( 0 < d <= 5000 ) 。
输出描述:
输出占一行:从路口 0 到 路口 V-1 的第二短的路径长度。
示例1
输入
复制 4 4 0 1 100 1 3 200 1 2 250 2 3 100
4 4 0 1 100 1 3 200 1 2 250 2 3 100
输出
复制 450
450
示例2
输入
复制 2 1 0 1 100
2 1 0 1 100
输出
复制 300
300
说明
路径可以重复走
次短路板子题。直接网上搞了个板子。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define M 200010
int n, m, s, lin[M], vis[M], dist1[M], dist2[M], cnt;
struct edge {
int to, len, nex;
}e[M];
int x, y,cur;
inline void add(int f, int t, int l)
{
e[++cnt].to = t;
e[cnt].len = l;
e[cnt].nex = lin[f];
lin[f] = cnt;
}
inline void spfa()
{
for (int i = 0; i < n; i++)
dist1[i] = dist2[i] = 21474836;
queue <int> q;
q.push(0);
dist1[0] = 0;
vis[0] = 1;
while (!q.empty())
{
int cur = q.front();
q.pop();
vis[cur] = 0;
for (int i = lin[cur]; i; i = e[i].nex)
{
int to = e[i].to;//以下三个if是关键,
if (dist1[to] > dist1[cur] + e[i].len)//最短更新,次短变最短
{
dist2[to] = dist1[to];
dist1[to] = dist1[cur] + e[i].len;
if (!vis[to]) vis[to] = 1, q.push(to);
}
if (dist2[to] > dist2[cur] + e[i].len)//次短由上一个点的次短更新,
{
dist2[to] = dist2[cur] + e[i].len;
if (!vis[to]) vis[to] = 1, q.push(to);
}
if (dist1[to] < dist1[cur] + e[i].len && dist2[to] > dist1[cur] + e[i].len)
{
dist2[to] = dist1[cur] + e[i].len;
if (!vis[to]) vis[to] = 1, q.push(to);
}
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < m; i++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c), add(b, a, c);
}
spfa();
printf("%d", dist2[n-1]);
}