【BFS】极其简单的最短路问题

题目描述

小C终于被小X感动了,于是决定与他看电影,然而小X距离电影院非常远,现在假设每条道路需要花费小X的时间为1,由于有数以万计的好朋友沿路祝贺,导致小X在通过某些路不得不耗费1的时间来和他们聊天,尽管他希望尽早见到小C,所以他希望找到一条最快时间到达电影院的路。
一开始小X在1号点,共有N个点,M条路,电影院为T号点。

输入

第一行2个正整数,分别为n,m,t
以下m行,每行3个数,表示连接的编号以及权值
(注意,可能会有重边)

输出

一行一个数,表示1到t的最短路

输入样例
10 12 6
3 9 2
6 9 2
6 2 1
3 1 1
1 9 2
2 8 2
7 10 1
7 2 1
10 0 1
8 1 1
1 5 2
3 7 2
输出样例
4

说明

30%:n<=10 m<=20
60%: n<=1000 m<=20000
100%: n<=5000000 m<=10000000

思路

这道题 S P F A SPFA SPFA只能拿80分
加快读90分
但是本题正解:BFS
我们由题可得每条边的权值要么1要么2
所以我们可以遇到边权为2时
加一个点,连接起点到新点
边权为1
连接新点与终点
边权为1
B F S BFS BFS
因为边权相等
就保证了第一次遇见 t t t就是最优的

#include<Algorithm>
#include<Iostream>
#include<Cstring>
#include<Cstdio>
#include<Cmath>
#include<Queue>
#define rr register
using namespace std;
int Ans[10000250],h[10000250],Bol[10000250];
int T,n,m,t,tt,x,s,y;
struct whw
{
	int w,h,s;
}wh[10000250];
void hw(int x,int s,int y)
{wh[++t]=(whw){s,h[x],y};h[x]=t;}
int read()
{
	int z=0,flag=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){z=z*10+ch-'0';ch=getchar();}
	return z*flag;
}
void Bfs()
{
	memset(Ans,0x3f,sizeof(Ans));
	queue<int>xsy;
	xsy.push(1);
	Bol[1]=1;
	Ans[1]=0;
	while(xsy.size())
	{
		x=xsy.front();
		xsy.pop();
		for(rr int i=h[x];i;i=wh[i].h)
			if(!Bol[wh[i].w])
			{
				Ans[wh[i].w]=wh[i].s+Ans[x];
				Bol[wh[i].w]=1;
				xsy.push(wh[i].w);
				if(wh[i].w==T)
				{
					printf("%d",Ans[wh[i].w]);
					return;
				}
			}
	}
}
int main()
{
	n=read();m=read();T=read();
	for(rr int i=1;i<=m;++i)
	{
		x=read();s=read();y=read();
		if(y==1)//如果边权为1
		{hw(x,s,y);hw(s,x,y);}//直接连接无向边
		else if(y==2)//如果为2
		{hw(x,n+(++tt),1);hw(n+tt,s,1);
		hw(n+tt,x,1);hw(s,n+tt,1);}//就设新点
	}
	Bfs();
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值