关于狄克斯特拉算法(dijkstra)总结
我们这里定义图的编号为:
1 2 3
4 5 6
7 8 9
图1:初始化的图,其中包含边的权值(耗时)。(这里图是有向图)。
图2:确定起点,然后向能直接走到的点走一下,记录此时的估计值:2 6 9.。
图3:找到距离起点最近的点,是正东边的那个点,这时候我们耗费权值为2。然后我们进行松弛操作,从起点到其东南方的点直接到的权值耗费为6,但是我们通过刚刚选定的点,我们找到了到这个点更近的方式,所以这个时候我们说从起点到其东南方向的点的权值更新值从6变成了5。这个时候我们就完成了第一次松弛操作。
图4:依旧是找距离起点最近的点。然后松弛我们发现这个时候从起点到其东南方的点的耗费权值从5又变成了4.这个时候我们完成了第二个松弛。
之后的方式同上:选定距离起点最近的点v。然后通过点v进行松弛操作。我们发现能够通过增加走到目的地方式的复杂度(多转弯)的方式我们能够松弛掉权值,使得耗费的权值更小。
模板:
void
Dij()//我们这里起点为1号编码点。我们这里的d[]表示从起点到这个点需要的权值。w[a][b]表示点a到点b这条边的权值.
{
int i,j,k,v,tmp;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++)
d[i]=w[1][i];//对应图不难理解,对于起点的初始化
d[1]=0;
vis[1]=1;
for(i=1;i<=n;i++)//控制连接点的次数,例如上图,九个点,就循环九次。
{
tmp=N;//这里N表示无穷大。也就是图上的99.
for(j=1;j<=n;j++)
{
if(tmp>d[j]&&!vis[j])
{
tmp=d[j];
v=j;
}
}//每次我们都找到距离起点最近的点v
vis[v]=1;
for(k=1;k<=n;k++)//然后进行松弛操作。
我们这里的d[]表示从起点到这个点需要的权值//加以强调其含义。
{
if(!vis[k])
d[k]=min(d[k],d[v]+w[v][k]);
}
}
}