极其简单的最短路问题
题目
小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
−
>
2
1->2
1−>2 变成
1
−
>
3
−
>
2
1->3->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;
}