圖論算法——最短路徑算法

求出最短路徑的長度

Floyed——Warshall算法 O(n^3)

Floyed算法,可以計算圖中任意兩點之間的最短路徑,適用於出現負邊權的情況。

算法描述
1.初始化:點u、v如果有邊相連,則dis[u][v]=w[u][v];
如果不相連,則dis[u][v]=0x7fffffff.
2.

for(k=1;k<=n;++k)
	for(i=1;i<=n;++i)
		for(j=1;j<=n;++j)
			if(dis[i][j]>dis[i][k]+dis[k][j])
			dis[i][j]=dis[i][k]+dis[k][j];
		/*如果有另外一條路比當前i到j的長度要短,那麼我們就跟新當前的路徑長度
		比如這裏i到j的路徑長度比i到k之後再從k到j的路徑長度要長,於是我們更新i到j的路徑長度
		*/

3.算法結束,dis[i][j]得出的就是從i到j的最短路徑算法。

算法變形

for(k=1;k<=n;++k)
	for(i=1;i<=n;++i)
		for(j=1;j<=n;++j)
			if(dis[i][j]>dis[i][k]+dis[k][j])
			dis[i][j]=dis[i][j]||(dis[i][k]&&dis[k][j]);
	//用這個辦法可以判斷一張圖中的兩點是否相連通

Dijkstra算法 O(N^2)

用來計算從一個點到其他所有點的最短路徑算法,是一種單源最短路徑算法。
Dijkstra不能處理存在負邊權的情況。

算法描述
設起點爲s,dis[v]表示s到v的最短路徑,pre[v]爲v的前驅節點,用來輸出路徑。
初始化:dis[v]=一個很大的值(v!=s),dis[s]=0,pre[s]=0;
for(i=1;i<=n;++i)
①在沒有被訪問過的點中找一個頂點u使得dis[u]是最小的。
②u標記爲已確定最短路徑
③for與u相連的每個未確定最短路徑的頂點v。
if(dis[u]+w[u][v]<dis[v]){
dis[v]=dis[u]+w[u][v];
pre[v]=u;
}
算法結束:dis[v]爲s到v的最短距離,pre[v]爲v的前驅節點,用來輸出路徑。

優化

在這裏插入代碼片

題目鏈接 https://www.luogu.com.cn/problem/P1462

SPFA

inline void SPFA(int s){//SLF優化的SPFA
    for(int i=1;i<=n;i++) dist[i]=0x3f3f3f3f;
    dist[s]=0;q.push_back(s);
    while(!q.empty()){
        int u=q.front();
        q.pop_front();
        f[u]=0;
        for(int i=head[u];i;i=bot[i].nx){
            int v=bot[i].nd;
            if(dist[v]>dist[u]+bot[i].co){
                dist[v]=dist[u]+bot[i].co;
                pre[v]=u;
                if(!f[v]){
                    f[v]=1;
                    if(q.empty()||dist[v]>dist[q.front()]) q.push_back(v);
                    else q.push_front(v);SLF優化
                }
                //不加slf優化的就是直接放入隊列的後面
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章