题目描述
小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;
}