最短路及其延伸

2021-09-25 05:39:08 字數 2640 閱讀 4504

想必最短路大家都很熟悉,那麼我們就先對最短路兩個重要的演算法總結一下;

prim其實就是以dp為基礎的最短路演算法,通過兩個節點的中介轉折點來更新兩點之間的最短路。從而解決任意兩點的最短路,時間複雜度是o(n^3);具體實現過程如下:

mp[maxn][maxn];//兩點之間的最短路 

for(int k=1;k<=n;++k)//k列舉狀態所以必須在外層迴圈

for(int i=1;i<=n;++i)

for(int j=1;j<=n;++j)

if(mp[i][j]>mp[i][k]+mp[k][j])

mp[i][j]=mp[i][k]+mp[k][j];

那麼基本演算法講完了,讓我們來加深對prim的理解,來一道例題:

題目背景

bb地區在**過後,所有村莊都造成了一定的損毀,而這場**卻沒對公路造成什麼影響。但是在村莊重建好之前,所有與未重建完成的村莊的公路均無法通車。換句話說,只有連線著兩個重建完成的村莊的公路才能通車,只能到達重建完成的村莊。

題目描述

給出bb地區的村莊數n,村莊編號從00到n-1,和所有m條公路的長度,公路是雙向的。並給出第i個村莊重建完成的時間t_i,你可以認為是同時開始重建並在第t_i 天重建完成,並且在當天即可通車。若t_i 為0則說明**未對此地區造成損壞,一開始就可以通車。之後有q個詢問(x, y, t),對於每個詢問你要回答在第t天,從村莊x到村莊y的最短路徑長度為多少。如果無法找到從x村莊到y村莊的路徑,經過若干個已重建完成的村莊,或者村莊x或村莊y在第t天仍未重建完成 ,則需要返回−1。

prim的基本思想就是:最開始只允許經過1號頂點進行中轉,接下來只允許經過1和2號頂點進行中轉……允許經過1~n號所有頂點進行中轉,求任意兩點之間的最短路程。用一句話概括就是:從i號頂點到j號頂點只經過前k號點的最短路程。

(仔細理解這段話,它揭露了這個演算法的本質並為本題提供了很好的方法)

到這裡我們已經知道,floyd演算法就是乙個利用其它點進行中轉來求最短路的步驟。

而我們再回頭看題意:

所有的邊全部給出,按照時間順序更新每乙個可用的點(即修建好村莊),對於每個時間點進行兩點之間詢問,求對於目前建設的所有村莊來說任意兩點之間的最短路

不正好就是floyd演算法中使用前k個節點更新最短路的思維嗎?

於是到了這裡,我們差不多也就知道這題如何寫了。

#include#define maxn 500

using namespace std;

int n,m,q,t[maxn],cnt=0,head[maxn],mp[maxn][maxn];

int main()

scanf("%d",&q);

int now=0;

for(int i=1;i<=q;++i)

if(t[x]>z||t[y]>z) printf("-1\n");

else if(mp[x][y]==1e9) printf("-1\n");

else printf("%d\n",mp[x][y]);

} return 0;

}

這就是最短路的演算法中最重要的乙個求單源最短路徑的演算法,正常情況下它的時間複雜度是o(n^2)在堆優化之後可以完美的降到nlogn;而且這個演算法極其穩定(不會像spfa一樣被卡),所以在以後的考試中建議大家都用dijkstra來跑最短路。

實現過程如下:

dis[maxn],vis[maxn];

priority_queue>q;

dj()

} }}

來一道例題:

題目背景

在艾澤拉斯大陸上有一位名叫歪嘴哦的神奇術士,他是部落的中堅力量

有一天他醒來後發現自己居然到了聯盟的主城暴風城

在被眾多聯盟的士兵攻擊後,他決定逃回自己的家鄉奧格瑞瑪

題目描述

在艾澤拉斯,有n個城市。編號為1,2,3,…,n。

城市之間有m條雙向的公路,連線著兩個城市,從某個城市到另乙個城市,會遭到聯盟的攻擊,進而損失一定的血量。

每次經過乙個城市,都會被收取一定的過路費(包括起點和終點)。路上並沒有收費站。

假設1為暴風城,n為奧格瑞瑪,而他的血量最多為b,出發時他的血量是滿的。

歪嘴哦不希望花很多錢,他想知道,在可以到達奧格瑞瑪的情況下,他所經過的所有城市中最多的一次收取的費用的最小值是多少。

這道題一看是有限制的最短路 ,有兩個維度,血量,和費用;

我們可能會不知所措,但這題麵中,有乙個非常顯眼的一句話:『』他所經過的所有城市中最多的一次收取的費用的最小值是多少。『』

這句話不就是典型的二分答案嗎?

想到二分答案,這道題的正解就呼之欲出了。

沒錯,就是二分答案加dijkstra檢查是否血量充足。

來看一看這道題的核心**:

bool dj(int m)

dis[1]=0;

q.push(make_pair(0,1));

while(q.size())

}} if(dis[n]<=b) return true;

else return false;

}int main()

printf("%d",ans);

}

CCSequence及其延伸

英文釋義,sequence 按順序排列。有關於這些個動作的,看參http 看下面這個 得空,每個動作演化一遍!插一句,addchild第2個引數zorder,越大,越在上面!brief runs actions sequentially,one after another.按順序的,乙個接乙個的,執...

最短路之dijkstra及其堆優化

dijkstra演算法用來解決單源最短路徑問題 通常來說就是求解乙個圖中兩節點的最短路徑 只適用於正權邊 該演算法的樸素想法是鬆弛的思想 即若dis 1 3 7 dis 1 2 1 dis 2 3 1 則節點2的存在就可以對1,3鬆弛 在鬆弛完乙個節點之後要選擇尚未進行鬆弛的節點鬆弛,且要選擇距起點...

最短路 最短路徑問題

題目描述 平面上有n個點 n 100 每個點的座標均在 10000 10000之間。其中的一些點之間有連線。若有連線,則表示可從乙個點到達另乙個點,即兩點間有通路,通路的距離為兩點直線的距離。現在的任務是找出從一點到另一點之間的最短路徑。input 共有n m 3行,其中 第一行為乙個整數n。第2行...