注意到第k條路徑的長度為2^k,則第k條路徑的長度會大於前k-1條路徑的
總和。由此我們可知兩個推斷:
(1)在新增第k條路徑時,如果路徑k連線的兩個城市a 、b已經通過其他路徑間接的連通了,那麼第k條路徑絕對不是ab間的最短路徑(第k條路徑之後的路徑也不可能有比當前ab路徑更短的路徑了,因為第k條路徑的長度會大於前k-1條路徑的總和)
(2)在新增第k條路徑時,如果路徑k連線的兩個城市a 、b是第一次被連通了(也就是說此前沒有任何路徑能連通ab,包括通過多條路徑間接連通),那麼路徑k就是ab之間的最短距離了,因為以後不可能存在更短的路徑連線ab,以後的單條路徑只會越來越長。
通過上述的推斷,我們可以利通過建立乙個最小連通樹的同時算出0號城市到各個城市的最小路徑。
具體的演算法:
(1)構造乙個並查集,每個城市指向自己,二維陣列d記錄城市之間的距離,初始化為-1不可達,d[i][i]初始化為0
(2)取第一條路徑,第一條路徑連線了城市a、b,城市a、b間最短路徑就是第一條路徑,然後把a、b合併在乙個集合裡
(3)再取一條路徑,
(一)如果這條邊連線的城市c、d,已經在同乙個集合裡了(即已經聯通了),那麼當前的路徑一定不是cd之間的最短路徑了,忽略之(理由是推斷(1)),繼續看下一條路徑。
(二)如果這條路徑連線的城市c、d不在同乙個集合裡(之前沒有聯通過),很好,這條路徑是cd之間的最短路徑(理由是推斷(2));除此之外我們還可以看看通過這條路徑能不能讓c集合裡的城市到d集合裡的城市之間的路徑更短呢?即是不是d[i][j]>(d[i][c]+dist+d[d][j]) ?(注意i和c乙個集合,d和j乙個集合),如果是的話可以更新一下這個值。
(4)重複(3)直到所有路徑都處理過了
0號城市到各個城市i的最小路徑結果就是d[0][i]了
#include#define n 100
int dis[n][n];
int father[n];
int findroot(int x)
}int mod(int x,int y)
return ret;
}int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=eof){
int i,j,k,a,b,x,y,dist;
for(i=0;i
Codeup最短路徑 最短路徑
n個城市,標號從0到n 1,m條道路,第k條道路 k從0開始 的長度為2 k,求編號為0的城市到其他城市的最短距離。第一行兩個正整數n 2 n 100 m m 500 表示有n個城市,m條道路,接下來m行兩個整數,表示相連的兩個城市的編號。n 1行,表示0號城市到其他城市的最短路,如果無法到達,輸出...
Codeup最短路徑 最短路徑問題
給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。輸入n,m,點的編號是1 n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數 s,t 起點s,...
最短路徑之最短路徑問題
提交 狀態 討論版 命題人 外部匯入 題目描述 平面上有n個點 n 100 每個點的座標均在 10000 10000之間。其中的一些點之間有連線。若有連線,則表示可從乙個點到達另乙個點,即兩點間有通路,通路的距離為兩點間的直線距離。現在的 任務是找出從一點到另一點之間的最短路徑。輸入共n m 3行,...