日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

最短路模板:dij,spfa与floyd

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 最短路模板:dij,spfa与floyd 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

圖論技能get!
一個超強大的建圖網站

最短路問題

1.dij算法

用于單源最短路
僅適用于沒有負邊權的情況
初始化dis數組為inf,dis【起點】=0;
tool:priority-queue(按dis升序)
先把起點放進隊列
每次取出排頭now,枚舉它能去的地方v;
如果——

dis[v]>dis[now]+p[i].w

說明目前從now走到v更優,就更新它,并入隊
最后now出列,并永遠不要回來(用人話說就是判重)

模板

void dij(){for(int i=1;i<=n;i++) dis[i]=INT_MAX;memset(jd,0,sizeof(jd));dis[s] = 0;priority_queue<pr,vector<pr>,greater<pr> >q;q.push(make_pair(0,s));int tot=0;while(!q.empty()){int now=q.top().second;q.pop();if(jd[now]) continue;jd[now]=1;for(int i=fi[now];~i;i=p[i].nxt){int v=p[i].to;//printf("#%d %d %d\n",p[i].nxt,now,v);if(dis[v]>dis[now]+p[i].w){dis[v]=dis[now]+p[i].w;q.push(make_pair(dis[v],v)); }}} }

(關于鏈式前向星存圖,請移步這里

證明

因為沒有負權
所以當前dis最小的值以后不可能從別的地方再更新
所以每次都取最小的,每個就只需取一次(n)

備注

因為優先隊列操作復雜度帶個log,所以
總復雜度為:O(nlogn)

從證明也可以看出,dij只適用于正權,那么有負權是怎么辦?
可以使用——

2.SPFA

“spfa已經死了”
和dij其實很類似,只是他不用優先隊列,也不判重,只要枚舉出度滿足上面那個關系式就可以進隊(當然,已經在的不要再進了)
當隊列為空結束

代碼

void spfa(double x){queue<int>q;mem(jd,1);for(int i=1;i<=n;i++) dis[i]=(double)inf;mem(nm,0);for(int i=0;i<m;i++){p[i].w -= x;}for(int i=1;i<=n;i++){q.push(i);}while(!q.empty()){int now=q.front();q.pop();jd[now]=0;for(int i=fi[now];~i;i=p[i].nxt){int v=p[i].to;if(dis[v]>=dis[now]+p[i].w){dis[v]=dis[now]+p[i].w;if(jd[v]==0) q.push(v);}}}for(int i=0;i<m;i++) p[i].w +=x;return; }

證明

因為不去重,隊列還是空了,說明已經沒有任何兩對滿足更新的關系式~~(暴力有什么好證明的)~~

備注

復雜度十分 玄學 不穩定
在特殊構造和稠密圖可能卡成O(mn)
直接裂開(2018NOIP血的教訓)
所以盡量還是用dij吧

floyd

多源!!!!
代碼《過于冗長》,直接看著代碼解釋吧。。。

代碼

for(int k = 1; k <= n; ++k)for(int i = 1; i <= n; ++i)for(int j = 1; j <= n; ++j)dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);

證明

(想不明白直接背)
dp[i][j][k]是從i到j經過中轉編號最大值為k的最短路
那么dp[i][j][k]更新到dp[i][j][k+1]就是看看經過k+1會不會更優唄
所以就是上面那個狀態轉移方程
最后dp[i][j][n]就是最終的最短路

踩蛋

(這個不是王建國寫的)

負環

如果存在一個總權值為負值的環,那么所有能碰到該環的兩點的最短路都會是無窮小(大風車吱吖吱悠悠的轉 )
此時spfa就會出現死循環
所以需要特殊判斷負環
如果一條路徑經過的點大于n,顯然它是經過了環
而你算著算著最短路它為啥溜號去跑環了呢?一定是出現了負環
從而進行判斷
關于代碼實現,我們可以在更新時加一行轉移:

nm[v]=nm[now]+1

代碼

bool spfa(){queue<int>q;mem(jd,0);for(int i=1;i<=n;i++) dis[i]=inf;mem(nm,0);q.push(1);jd[1]=1;dis[1]=0;while(!q.empty()){int now=q.front();q.pop();jd[now]=0;for(int i=fi[now];~i;i=p[i].nxt){int v=p[i].to;if(dis[v]>dis[now]+p[i].w){dis[v]=dis[now]+p[i].w;nm[v]=nm[now]+1;if(jd[v]==0) q.push(v);if(nm[v]>=n){return true;}}}}return false; }

覺得明白了可以來洛谷水道模板

就醬!拜拜~

總結

以上是生活随笔為你收集整理的最短路模板:dij,spfa与floyd的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。