void dijkstra()}}}
void spfa()}} }
演算法限制
時間複雜度
dijkstra
無法處理負權邊,遍歷過程具有拓撲序
o(n2)
dijkstra_heap
無法處理負權邊,遍歷過程具有拓撲序
o(mlogn)
bellman_ford
可處理負權邊,時間成本太高,遍歷過程不具拓撲序
o(nm)
spfa
可處理負權邊,遍歷過程不具拓撲序
o(km),特殊情況下可能退化成o(nm)
時間複雜度:o(nmlogn)
時間複雜度:o(n3)
void floyd()
題目鏈結
建立乙個虛擬源點,從虛擬源點向各個起始點連一條權值為0的邊。則原問題等價於從虛擬源點到終點的最短路徑長度。
如此便成功將乙個多源最短路問題轉化為了乙個單源最短路問題。
#include #include #include #include #include using namespace std;const int n=1e3+10,m=2e4+10;
struct edgeedge[m+n<<1];int idx;
int h[n];
int dis[n],vis[n];
int n,m,s,t;
void add_edge(int u,int v,int w);h[u]=idx;}
void dijkstra()}}
}int main()
scanf("%d",&s);
for(int i=1;i<=s;i++)
dijkstra();
if(dis[t]==0x3f3f3f3f)printf("-1\n");
else printf("%d\n",dis[t]);
}return 0;
}
題目鏈結
分層圖實際上是借助動態規劃的思想考慮最短路問題,而後再用求最短路的演算法來解決的一種思想。考慮在每層的圖上各點間連原有的邊,在相鄰層之間連權值為0的邊。
而後原問題就轉化為從第一層圖的起點走到最後一層圖的終點的最短路問題。
#include #include #include #include #include using namespace std;const int n=1e4+10,m=5e4+10,maxk=11;
struct edgeedge[m*maxk*4]; int idx;
int h[n*maxk];
int dis[n*maxk],vis[n*maxk];
int n,m,k,s,t;
void add_edge(int u,int v,int w);h[u]=idx;}
void dijkstra(int s)
} }}int main()
for(int i=0;i對於邊權只有0和1的圖,求最短路可以用雙端佇列bfs。
在每次鬆弛操作時,若邊權為0則放入隊首,若邊權為1則放到隊尾。
void bfs()}}
}
題目鏈結
在dijkstra原演算法上稍作修改。每次鬆馳操作更新最短路時,同時更新計數陣列。
若更新不成功,轉而判斷當前路徑是否與當前最短路長度相等,若是則累加計數。
說明:該題可用dijkstra演算法求解的乙個必要條件是:dijkstra演算法求解的過程,對圖的遍歷順序是該圖的乙個拓撲序。
而spfa演算法不滿足拓撲序,故不便於求解該類問題。
#include #include #include #include #include using namespace std;const int n=1e6+10,m=2e6+10,mod=1e5+3;
struct edgeedge[m<<1]; int idx;
int h[n];
int dis[n],vis[n],cnt[n];
int n,m;
void add(int u,int v,int w);h[u]=idx;}
void dijkstra(int s)
else if(dis[to]==dis[k]+w)
} }}
int main()
dijkstra(1);
for(int i=1;i<=n;i++)printf("%d\n",cnt[i]);
return 0;
}
題目鏈結
該題綜合了最短路、最短路計數、次短路、次短路計數,值得一做。對於求解次短路。
仿照拆點的思想,將乙個點拆成兩個點,dis[i][0]表示最短路,dis[i][1]表示次短路,然後進行求解。
在原dijkstra演算法上稍作修改:
若可更新最短路,則將最短路淪為次短路,然後更新最短路,同時將最短路與次短路入隊;
若可更新次短路,則將次短路更新,然後將次短路入隊。
#include #include #include #include #include using namespace std;const int n=1e3+10,m=1e4+10;
struct edgeedge[m];int idx;
int h[n];
void add_edge(int u,int v,int w);h[u]=idx;}
struct point
};int dis[n][2],vis[n][2],cnt[n][2];
int n,m,s,t,t;
void init()
int dijkstra()
);
while(!q.empty())
);dis[to][0]=dis[p][tp]+w;cnt[to][0]=cnt[p][tp];
q.push();
}else if(dis[to][0]==dis[p][tp]+w)
cnt[to][0]+=cnt[p][tp];
else if(dis[to][1]>dis[p][tp]+w));}
else if(dis[to][1]==dis[p][tp]+w)
cnt[to][1]+=cnt[p][tp];}}
int res=cnt[t][0];
if(dis[t][1]==dis[t][0]+1)res+=cnt[t][1];
return res;
}int main()
scanf("%d%d",&s,&t);
printf("%d\n",dijkstra());
}return 0;
}
最短路總結
寫個部落格記錄一下最短路的幾種演算法,盡量做最正確的解答,減少大家的疑惑,網上有好多講的都抄來抄去,還有好多講的都是錯誤的。熟悉的最短路演算法就幾種 bellman ford,dijkstra,spfa,floyd,下面針對這幾個演算法具體解析一下。首先說明一點,就是關於負環的問題。bellman ...
最短路總結
穿越空間的限制,走最短的路找到你 u v之間的最短路滿足以下限制 對任意k g v,e 有 dist u,v dis u,k dis k,j 關鍵操作 鬆弛 void relax int i,int j,int k floyd void floyd 複雜度o v 3 可處理負環 拓展把所有邊存成負的...
最短路總結
首先是dij演算法,這是我第乙個掌握的最短路演算法!再來是bellman ford演算法,這個演算法比較容易理解,而且考慮到了負環的存在。記住,它對圖中的邊進行了 v 1次操作!首先,對d進行初始化 還有乙個spfa演算法 摘錄於學長空間 設立乙個先進先出的佇列用來儲存待優化的結點,優化時每次取出隊...