新冠病毒要回家

链接: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]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值