题目传送门
分析题目:
表示第
a
i
a_i
ai
个停留站到第
b
i
b_i
bi
个停留站需要
c
i
c_i
ci
的时间
从
b
i
b_i
bi
个停留站到第
a
i
a_i
ai
个停留站也需要
c
i
c_i
ci
的时间
所以本题就是最短路径算法
再看题目的数据范围:
1≤n≤2500, 1 0 5 10^5 105≤m≤2× 1 0 5 10^5 105,1≤c≤ 1 0 6 10^6 106
时间限制:1s
很明显,时间复杂度为O(
n
3
n^3
n3)
的Floyd算法绝对不行
于是乎,时间复杂度为O(
n
2
n^2
n2)
的Dijkstra算法是目前的最优选择
介绍迪杰斯特拉算法:
设置dis数组,将源点设为0,其余无限
将所有与源点有连边的终点赋值为该连边的权值
设定两个集合 V V V和 S S S,初始时 V V V集合为所有集合, S S S集合为源点
每次取与源点最接近的那条边的终点,将那个点加入集合 S S S
加入后,对 V V V- S S S集合中的所有点进行松弛操作,即把原边的权值缩小为已知最小
依次进行 V V V次,最后松弛完毕后的dis数组即为正确答案。
代码:
#include<bits/stdc++.h>
using namespace std;
const int inf=INT_MAX;
int n,m;
int g[2505][2505];
int u,v,w;
bool book[2505];
int dis[2505];
int minn=inf;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
dis[i]=inf;
for (int j=1 ;j <= n ; j++)
{
if(i==j)
{
g[i][j]=0;
}
else
{
g[i][j] = inf;
}
}
}
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&u,&v,&w);
g[u][v]=min(w,g[u][v]);
g[v][u]=min(w,g[v][u]);
}
for(int i=1;i<=n;i++)
{
dis[i]=g[1][i];
}
book[1]=true;
for (int i=1;i<n;i++)
{
minn=inf;
int t;
for(int j=1;j<=n;j++)
{
if(book[j]==false&&dis[j]<minn)
{
t=j;
minn=dis[j];
}
}
book[t]=true;
for(int j=1;j<=n;j++)
{
if(g[t][j]<inf)
{
if(dis[j]>dis[t]+g[t][j])
{
dis[j]=dis[t]+g[t][j];
}
}
}
}
printf ("%d\n",dis[n]);
return 0;
}