Roadblocks(次短路)

Roadblocks(次短路)

题目描述
原题来自:USACO 2006 Nov. Gold

贝茜把家搬到了一个小农场,但她常常回到 FJ 的农场去拜访她的朋友。贝茜很喜欢路边的风景,不想那么快地结束她的旅途,于是她每次回农场,都会选择第二短的路径,而不象我们所习惯的那样,选择最短路。

贝茜所在的乡村有 条双向道路,每条路都连接了所有的 个农场中的某两个。贝茜居住在农场 ,她的朋友们居住在农场 (即贝茜每次旅行的目的地)。

贝茜选择的第二短的路径中,可以包含任何一条在最短路中出现的道路,并且一条路可以重复走多次。当然第二短路的长度必须严格大于最短路(可能有多条)的长度,但它的长度必须不大于所有除最短路外的路径的长度。

一句话题意:给一张无向图,求这张图的严格次短路之长。

输入格式

输入文件的第 1行为两个整数n和 r用空格隔开;

第2-r+1 行:每行包含三个用空格隔开的整数a 、b 和 d(1<=d<=5000) ,表示存在一条长度为 d 的路连接农场a和农场b 。

输出格式
输出仅一个整数,表示从农场 1 到农场 n 的第二短路的长度。

样例
输入

4 4
1 2 100
2 4 200
2 3 250
3 4 100

输出
450

次短路板

AC代码:

#include<stdio.h>
#include<string.h>
#include<queue>
#define inf 0x3f3f3f3f
#include<algorithm>
using namespace std;
typedef pair<int, int>pll;//pair相当于一个结构体中有两个变量first,second
const int N=1e6+10;
int cnt,n,r;
int head[N];
int dis[N];//最短路 
int d[N];//次短路 
struct pp
{
	int to,next,w;
}p[N];
void add(int x,int y,int z)
{
	p[cnt].to=y;
	p[cnt].w=z;
	p[cnt].next=head[x];
	head[x]=cnt++;
}
void spfa()
{
	priority_queue<pll,vector<pll>,greater<pll> >q;//默认从大到小,这里从小到大 
	memset(dis,inf,sizeof(dis));
	memset(d,inf,sizeof(d));//两个都初始
	dis[1]=0;//源点到源点的最短路为0
	//注意源点到源点的次短路不为0
	q.push({0,1});//first为路程,second为顶点 
	while(!q.empty())
	{
		pll u=q.top();//队列队首为front,优先队列为top 
		q.pop();
		int x=u.second;//是u不是q 
		int w=u.first;
		for(int i=head[x];~i;i=p[i].next)//~是将对应内存单元的内容按位求反
		{//i=-1时,~i=0
			int y=p[i].to;
			if(dis[y]>w+p[i].w)//比当前最短路短 
			{
				d[y]=dis[y];//次短路更新为当前最短路 
				dis[y]=w+p[i].w;//当前最短路更新为比当前最短路还短的 
				q.push({dis[y],y});
				q.push({d[y],y});
			}
			if(dis[y]<w+p[i].w&&d[y]>w+p[i].w)//比最短路长,次短路小 
			{
				d[y]=w+p[i].w;//更新次短路 
				q.push({d[y],y});
			}
		}
	}
}
int main()
{
	int a,b,c,i,j,k;
	memset(head,-1,sizeof(head));
	scanf("%d%d",&n,&r);
	while(r--)
	{
		scanf("%d%d%d",&a,&b,&c);
		add(a,b,c);
		add(b,a,c);
	}
	spfa();
	printf("%d\n",d[n]);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值