对于最短路径问题,这里介绍一种O(N^2)的求解方法。
对于求最短路径的问题一般都会给出一幅图,或者边与边的关系。如上图。
假设我们起点是A,我们要求到F的最短距离,我们会怎么做?
首先,因为A是起点,所以我们把对于每个点都有个参数,相对于A的距离,默认除了A到A为0,其他都是无穷大。
从起点A开始,我们更新与A相连通的点到A的距离,并把A点标记。如图:
我们遍历一次所有点与A的距离,找到最小的,这里是点B。
以它为起点,把它周围未被标记的点拿来做比较,显然,像F这种没有与A练过的点,当前距离就会变成min(dis[B]+maze[B][F],INF),就是B到起点的距离加上BF之间的距离。而像c这种与A直接相连的点,当前距离就会变成min(dis[B]+maze[B][C],dis[c]),所以按照我们每次只需要比较当前点到当前状态起点的和与当前点到起点的距离就可以了。
然后我们遍历发现,当前未被标记且到起点距离最小点的点是C点。我们更新连接了C的所有点。同样利用上面的min公式。
同理,更新D点的邻点。
再把更新E点的邻点。
最后再更新F点。发现F点周围所有点都被标记了,不做更新。
再遍历,发现图中所有点都被遍历了,算法结束。
这个时候,我们已经求出了所有点到起点的最小距离。
可以直接输出dis[F]求得A到F的最短路径。
注意:
上面的图重点是看每次变化找的起点和与出发点路径的变化。
当前起点是当前未被标记且到出发点距离最近的点。
更新的点都是与该起点直接相连并未被标记的点。
因为并没有无穷大这个数,所以我们把INF设为一个我们计算不能到达的数,这里的数接近int的上限,可以近似看作正无穷。
参考代码如下:
#include"iostream"
#include"cstring"
#include"cstdio"
using namespace std;
#define INF 0x7f7f7f7f
const int N = 105; //点的个数上限
int maze[N][N];
int dis[N];
bool vis[N];
//点的个数和边的条数
int n,m;
void init()
{
memset(maze,INF,sizeof(maze));
memset(dis,INF,sizeof(dis));
memset(vis,false,sizeof(vis));
}
void dijkstra(int st)
{
dis[st]=0;
for(int i=1; i<=n; i++)
{
//找到和起点距离最短的点
int minx=INF;
int minmark;
for(int j=1; j<=n; j++)
{
if(vis[j]==false&&dis[j]<=minx)
{
minx=dis[j];
minmark=j;
}
}
//并标记
vis[minmark]=true;
//更新所有和它连接的点的距离
for(int j=1; j<=n; j++)
{
if(vis[j]==false&&dis[j]>dis[minmark]+maze[minmark][j])
dis[j]=dis[minmark]+maze[minmark][j];
}
}
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
if(n==0&&m==0) break;
//每组数据都要初始化
init();
for(int i=1; i<=m; i++)
{
int x,y,len;
scanf("%d %d %d",&x,&y,&len);
if(x!=y&&maze[x][y]>len)
{
maze[y][x]=len;
maze[x][y]=len;
}
}
//以1为起点跑一次dij
dijkstra(1);
//输出到n的距离
printf("%d\n",dis[n]);
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-09 07:02:02