關於單源最短路徑的問題


在此之前一直在看圖算法,但是看的多了不免會有些混淆,今天我就算是進行一次自我總結吧。

單源最短路徑算法1:Dijkstra 算法

這個算法是處理單元最短路徑問題的,他的本質是一種貪心算法。

實現: 

將圖G中所有的頂點V分成兩個頂點集合S和T。以v為源點已經確定了最短路徑的終點並入S 集合中,S初始時只含頂點v,T則是尚未確定到源點v最短路徑的頂點集合。然后每次從T集合中選擇S集合點中到T路徑最短的那個點,並加入到集合S中,並把這個點從集合T刪除。直到T集合為空為止。
具體步驟
1、選一頂點v為源點,並視從源點v出發的所有邊為到各頂點的最短路徑(確定數據結構:因為求的是最短路徑,所以①就要用一個記錄從源點v到其它各頂點的路徑長度 數組dist[],開始時,dist是源點v到頂點i的直接邊長度,即dist中記錄的是鄰接陣的第v行。②設一個用來記錄從源點到其它頂點的路徑數組path[],path中存放路徑上第i個頂點的前驅頂點)。
2、在上述的最短路徑dist[]中選一條最短的,並將其終點(即<v,k>)k加入到集合s中。
3、調整T中各頂點到源點v的最短路徑。 因為當頂點k加入到集合s中后,源點v到T中剩余的其它頂點j就又增加了經過頂點k到達j的路徑,這條路徑可能要比源點v到j原來的最短的還要短。調整方法是比較dist[k]+g[k,j]與dist[j],取其中的較小者。
4、再選出一個到源點v路徑長度最小的頂點k,從T中刪去后加入S中,再回去到第三步,如此重復,直到集合S中的包含圖G的所有頂點。

  

代碼的實現:

int cost[MAX_V][MAX_V] ;//cost[u][v]表示邊e=(u,v)的權值
int d[MAX_V] ;//頂點S出發的最短距離
bool used[MAX_V] ;//已經使用過的點
int V ;//頂點數
void dijkstra(int s)
{
    fill(d,d+V,INF);
    fill(used,used+V,false);
    d[s]=0;
    while(true)
    {
        int v=-1;
        for(int u=0;u<V;u++)
        {
            if(!used[u]&&(v==-1||d[u]<d[v]))
            v=u;
        }
        if(v==-1)    break;
        used[v]=true;
        for(int u=0;u<V;u++)
        {
            d[u]=min(d[u],d[v]+cost[v][u]);
        }
    }
}

下面是利用優先隊列實現的

struct edge{
    int to,cost;
};
typedef pair<int,int> P;
int V;
vector<edge>G[MAX_N];
int d[MAX_N];
void dijkstra(int s)
{
    priority_queue<P,vector<P>,greater<P> > que;
    fill(d,d+v,INF);
    d[s]=0;
    que.push(P(0,s));
    while(!que.empty())
    {
        P p=que.top();que.pop();
        int v=p.second;
        if(d[v]<p.first)    continue;
        for(int i=0;i<G[v].size();i++)
        {
            edge e=G[v][i];
            if(d[e.to]>d[v]+e.cost)
            {
                d[e.to]=d[v]+e.cost;
                que.push(P(d[e.to],e.to));
            }
        }
    }
}

單源最短路徑算法2 Bellman-Ford:

  由於dijkstra算法不能處理帶有負數權值變得問題,所以還要學會一種能夠處理負數權值邊問題

  這個算法算是一種動態規划算法。

struct edge{
    int from,to,cost;
};
edge es[MAX_N];
int d[MAX_N];
int V,E;
void short_path(int s)
{
    for(int i=0;i<V;i++)    d[i]=INF;
    d[s]=0;
    while(true)
    {
        bool update=false;
        for(int i=0;i<E;i++)
        {
            edge e=es[i];
            if(d[e.from]!=INF&&d[e.to]>e.cost+d[e.from])
            {
                d[e.to]=e.cost+d[e.from];
                update=true;
            }
        }
        if(!update)    break;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM