• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 200, comments - 8, trackbacks - 0, articles - 0

            Dijkstra算法(單源最短路徑)

            Posted on 2013-10-16 20:31 鑫龍 閱讀(591) 評論(0)  編輯 收藏 引用 所屬分類: 數據結構與算法

                                                                 Dijkstra算法(單源最短路徑)

                  單源最短路徑問題,即在圖中求出給定頂點到其它任一頂點的最短路徑。在弄清楚如何求算單源最短路徑問題之前,必須弄清楚最短路徑的最優子結構性質。

            一.最短路徑的最優子結構性質

               該性質描述為:如果P(i,j)={Vi....Vk..Vs...Vj}是從頂點i到j的最短路徑,k和s是這條路徑上的一個中間頂點,那么P(k,s)必定是從k到s的最短路徑。下面證明該性質的正確性。

               假設P(i,j)={Vi....Vk..Vs...Vj}是從頂點i到j的最短路徑,則有P(i,j)=P(i,k)+P(k,s)+P(s,j)。而P(k,s)不是從k到s的最短距離,那么必定存在另一條從k到s的最短路徑P'(k,s),那么P'(i,j)=P(i,k)+P'(k,s)+P(s,j)<P(i,j)。則與P(i,j)是從i到j的最短路徑相矛盾。因此該性質得證。

            二.Dijkstra算法

               由上述性質可知,如果存在一條從i到j的最短路徑(Vi.....Vk,Vj),Vk是Vj前面的一頂點。那么(Vi...Vk)也必定是從i到k的最短路徑。為了求出最短路徑,Dijkstra就提出了以最短路徑長度遞增,逐次生成最短路徑的算法。譬如對于源頂點V0,首先選擇其直接相鄰的頂點中長度最短的頂點Vi,那么當前已知可得從V0到達Vj頂點的最短距離dist[j]=min{dist[j],dist[i]+matrix[i][j]}。根據這種思路,

            假設存在G=<V,E>,源頂點為V0,U={V0},dist[i]記錄V0到i的最短距離,path[i]記錄從V0到i路徑上的i前面的一個頂點。

            1.從V-U中選擇使dist[i]值最小的頂點i,將i加入到U中;

            2.更新與i直接相鄰頂點的dist值。(dist[j]=min{dist[j],dist[i]+matrix[i][j]})

            3.知道U=V,停止。

            代碼實現:

            /*Dijkstra求單源最短路徑 2010.8.26*/
             
            #include <iostream>
            #include<stack>
            #define M 100
            #define N 100
            using namespace std;

            typedef struct node
            {
                int matrix[N][M];      //鄰接矩陣 
                int n;                 //頂點數 
                int e;                 //邊數 
            }MGraph; 

            void DijkstraPath(MGraph g,int *dist,int *path,int v0)   //v0表示源頂點 
            {
                int i,j,k;
                bool *visited=(bool *)malloc(sizeof(bool)*g.n);
                for(i=0;i<g.n;i++)     //初始化 
                {
                    if(g.matrix[v0][i]>0&&i!=v0)
                    {
                        dist[i]=g.matrix[v0][i];
                        path[i]=v0;     //path記錄最短路徑上從v0到i的前一個頂點 
                    }
                    else
                    {
                        dist[i]=INT_MAX;    //若i不與v0直接相鄰,則權值置為無窮大 
                        path[i]=-1;
                    }
                    visited[i]=false;
                    path[v0]=v0;
                    dist[v0]=0;
                }
                visited[v0]=true;
                for(i=1;i<g.n;i++)     //循環擴展n-1次 
                {
                    int min=INT_MAX;
                    int u;
                    for(j=0;j<g.n;j++)    //尋找未被擴展的權值最小的頂點 
                    {
                        if(visited[j]==false&&dist[j]<min)
                        {
                            min=dist[j];
                            u=j;        
                        }
                    } 
                    visited[u]=true;
                    for(k=0;k<g.n;k++)   //更新dist數組的值和路徑的值 
                    {
                        if(visited[k]==false&&g.matrix[u][k]>0&&min+g.matrix[u][k]<dist[k])
                        {
                            dist[k]=min+g.matrix[u][k];
                            path[k]=u; 
                        }
                    }        
                }    
            }

            void showPath(int *path,int v,int v0)   //打印最短路徑上的各個頂點 
            {
                stack<int> s;
                int u=v;
                while(v!=v0)
                {
                    s.push(v);
                    v=path[v];
                }
                s.push(v);
                while(!s.empty())
                {
                    cout<<s.top()<<" ";
                    s.pop();
                }


            int main(int argc, char *argv[])
            {
                int n,e;     //表示輸入的頂點數和邊數 
                while(cin>>n>>e&&e!=0)
                {
                    int i,j;
                    int s,t,w;      //表示存在一條邊s->t,權值為w
                    MGraph g;
                    int v0;
                    int *dist=(int *)malloc(sizeof(int)*n);
                    int *path=(int *)malloc(sizeof(int)*n);
                    for(i=0;i<N;i++)
                        for(j=0;j<M;j++)
                            g.matrix[i][j]=0;
                    g.n=n;
                    g.e=e;
                    for(i=0;i<e;i++)
                    {
                        cin>>s>>t>>w;
                        g.matrix[s][t]=w;
                    }
                    cin>>v0;        //輸入源頂點 
                    DijkstraPath(g,dist,path,v0);
                    for(i=0;i<n;i++)
                    {
                        if(i!=v0)
                        {
                            showPath(path,i,v0);
                            cout<<dist[i]<<endl;
                        }
                    }
                }
                return 0;
            }




            久久久久成人精品无码| 99久久精品这里只有精品| 国内精品久久久久久不卡影院| 热久久这里只有精品| 久久综合五月丁香久久激情| 久久人人爽人人爽人人片av麻烦| 久久精品无码一区二区WWW| 国内精品久久久久影院日本| 激情五月综合综合久久69| 久久综合亚洲色HEZYO国产| 99久久精品国产高清一区二区| 久久本道久久综合伊人| 色综合久久久久久久久五月| 国产高潮国产高潮久久久91| 中文字幕无码久久精品青草| 久久国产精品久久精品国产| 久久精品一区二区三区AV| 色噜噜狠狠先锋影音久久| 亚洲香蕉网久久综合影视 | 久久综合国产乱子伦精品免费| 久久精品国产精品亚洲精品 | 欧美久久天天综合香蕉伊| 久久精品一本到99热免费| 久久天天躁狠狠躁夜夜2020| 久久久久无码精品国产| 一本综合久久国产二区| 久久本道久久综合伊人| 国产精品一区二区久久精品无码| 2021最新久久久视精品爱| 激情综合色综合久久综合| 国产福利电影一区二区三区久久老子无码午夜伦不 | 青草久久久国产线免观| 久久综合狠狠色综合伊人| 久久亚洲私人国产精品| 久久久久久国产精品美女| 久久亚洲精品无码aⅴ大香 | 99久久99久久精品国产片果冻| 久久夜色精品国产| 亚洲欧美精品一区久久中文字幕| 久久久久国产日韩精品网站| 91精品国产综合久久香蕉 |