求出最短路徑的長度
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優化的就是直接放入隊列的後面
}
}
}
}