码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构之Dijkstra

时间:2015-03-29 12:12:04      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:

总感觉Dijkstra跟prim思路很像,现在仔细想想虽然都算的上贪心,但是Dijkstra比prim复杂一点

prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的点集合A,另一个集合为未加入生成树的点B,它的具体实现过程是:

第1步:所有的点都在集合B中,A集合为空。

第2步:任意以一个点为开始,把这个初始点加入集合A中,从集合B中减去这个点(代码实现很简单,也就是设置一个标示数组,为false表示这个点在B中,为true表示这个点在A中),寻找与它相邻的点中路径最短的点,如后把这个点也加入集合A中,从集合B中减去这个点(代码实现同上)。

第3步:集合A中已经有了多个点,这时两个集合A和B,只要找到A集合中的点到B集合中的点的最短边,可以是A集合中的与B集合中的点的任意组合,把这条最短边有两个顶点,把在集合B中的顶点加入到集合A中,(代码实现的时候有点技巧,不需要枚举所有情况,也就是更新操作)。

第4步:重复上述过程。一直到所有的点都在A集合中结束。

Dijkstra比prim算法的过程稍微多一点点步骤,但是思想确实巧妙的,也是贪心原理,它的目的是求某个源点到目的点的最短距离,总的来说,dijkstra算法也就是求某个源点到目的点的最短路,求解的过程也就是求源点到整个图的最短距离,次短距离,第三短距离等等(这些距离都是源点到某个点的最短距离)。。。。。求出来的每个距离都对应着一个点,也就是到这个点的最短距离,求的也就是原点到所有点的最短距离,并且存在了一个二维数组中,最后给出目的点就能直接通过查表获得最短距离。

第1步:以源点(假设是s1)为开始点,求最短距离,如何求呢? 与这个源点相邻的点与源点的距离全部放在一个数组dist[]中,如果不可达,dist[]中为最大值,这里说一下,为什么要是一维数组,原因是默认的是从源点到这个一维数组下标的值,只需要目的点作为下标就可以,这时从源点到其他点的最短的“一”条路径有了,只要选出dist[]中最小的就行(得到最短路径的另一个端点假设是s2)。

第2步:这时要寻找源点(假设是s1)到另外点的次短距离,这个距离或者是dist[]里面的值,或者是从第1步中选择的那个最短距离 + 从找到点(假设是s2)出发到其他点的距离(其实这里也是一个更新操作,更新的是dist[]里面的值),如果最短距离 + 从这点(假设是s2)到其他点的距离,小于dist[]里面的值,就可以更新dist[]数组了,然后再从dist[]数组中选一个值最小的,也就是第“二”短路径(次短路径)。

第3步:寻找第“三”短路径,这时同上,第二短路径的端点(s3)更新与之相邻其他的点的dist[]数组里面的值。

第4步:重复上述过程n - 1次(n指的是节点个数),得出结果,其实把源点到所有点的最短路径求出来了,都填在了dist[]表中,要找源点到哪个点的最短路,就只需要查表了。

附一道题:

 hdu1874

#include<iostream>
using namespace std;
const int maxnum=1005;
const int maxint=99999;
int dist[maxnum];//起点到终点的距离
int c[maxnum][maxnum];//用于储存两点之间的距离
void Dijkstra(int S,int N,int * dist,int  c[maxnum][maxnum])
{
    bool s[maxnum];//判断是否已加入集合S中
    //初始化起始点到其他点的距离
   for(int i=0;i<N;i++)
    {
        dist[i]=c[S][i];
        s[i]=0;
    }
     //起始点被标记,最短距离为0
    s[S]=1;
    dist[S]=0;
    //遍历剩下n-1个点

       for(int i=1;i<N;i++)
    {
        int u=S;
        int temp=maxint;
        //找出尚未标记的点中,与起始点距离最短的
        for(int j=0;j<N;j++)
            if(!s[j]&&dist[j]<temp)
            {
                u=j;
                temp=dist[j];
            }
        s[u]=1;
        //最难理解的地方:找到当前已于起始点联通的点的最短距离,随着每一次遍历,会更新,最终达到最短

       for(int k=0;k<N;k++)
            if(!s[k]&&dist[k]>dist[u]+c[u][k])
            {
                dist[k]=dist[u]+c[u][k];
            }

    }

}

 int main ()
{
    int   N,M;
   while(cin>>N>>M)
   {
        int A,B,X;
        for(int i=0;i<N;i++)
           for(int j=0;j<N;j++)
                c[i][j]=maxint;
        for(int i=1; i<=N; ++i)
           dist[i] = maxint;

          for(int i=0;i<M;i++)
        {
            cin>>A>>B>>X;
            if(X<c[A][B])
            {
                c[A][B]=X;
                c[B][A]=X;
            }
        }

       int S,E;
        cin>>S>>E;
        Dijkstra(S,N,dist,c);

         if(dist[E]==maxint)
            cout<<"-1"<<endl;
        else
            cout<<dist[E]<<endl;
    }
    return 0;
}

 

数据结构之Dijkstra

标签:

原文地址:http://www.cnblogs.com/ACWQYYY/p/4375428.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!