极其简单的最短路问题

极其简单的最短路问题

题目

小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

思路

这道题看起来是一道最短路题,但是如果用最短路做会超时,那怎么办呢?

由题目可得,边的权值只有可能是1或者2。
那么我们可以把权值为2的边转换为权值为1的两条边,比如这样:
1 − &gt; 2 1-&gt;2 1>2 变成 1 − &gt; 3 − &gt; 2 1-&gt;3-&gt;2 1>3>2
那么这样,我们就可以用 b f s bfs bfs来做了。

代码

#include<cstdio>
#include<queue>
using namespace std;
struct note
{
	int to,next;
}e[20000001];
int n,m,t,le[40000001],k,x,y,z,f[40000001];
bool in[40000001];
int read()//快读
{
	int ans=0;
	char c=getchar();
	while (c>='0'&&c<='9')
	{
		ans=ans*10+c-48;
		c=getchar();
	}
	return ans;
}
void jl(int xx,int yy)//建邻接表
{
	e[++k]=(note){yy,le[xx]};
	le[xx]=k;
	e[++k]=(note){xx,le[yy]};
	le[yy]=k;
}
void bfs()//bfs
{
	in[1]=1;
	queue<int>a;
	a.push(1);
	while (!a.empty())
	{
		int h=a.front();
		a.pop();
		for (int i=le[h];i;i=e[i].next)
		if (!in[e[i].to])
		{
			a.push(e[i].to);
			in[e[i].to]=1;
			f[e[i].to]=f[h]+1;
		}
		if (in[t])
		{
			printf("%d",f[t]);
			return ;
		}
	}
}
int main()
{
	n=read();m=read();t=read();//读入
	for (int i=1;i<=m;i++)
	{
		x=read();y=read();z=read();//读入
		if (z==1) jl(x,y);//建邻接表
		else//把权值为二的边转化成两条边
		{
			jl(x,++n);
			jl(n,y);
		}
	}
	bfs();//bfs
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值