題目描述:
n個城市,標號從0到n-1,m條道路,第k條道路(k從0開始)的長度為2^k,求編號為0的城市到其他城市的最短距離
輸入: 第一行兩個正整數n(2<=n<=100)m(m<=500),表示有n個城市,m條道路
接下來m行兩個整數,表示相連的兩個城市的編號
輸出: n-1行,表示0號城市到其他城市的最短路,如果無法到達,輸出-1,數值太大的以mod 100000 的結果輸出。
樣例輸入:
4 41 2
2 31 3
0 1樣例輸出:89
11
(大數mod處理)本題路徑值為2^k (k最多500),結果取膜100000
由 (a+b)%m = (a%m +b%m)%m
得(2^a+2^b+·····2^k)%100000=(2^a%100000+2^b%100000 +·····2^k%100000)%100000
所以得到每條路徑%100000的值就行,最後相加再取膜100000就行
由a * b % m = (a % m * b % m)%m
2^( k+1)%100000=(2^k %100000 * 2%100000 )%100000 =2^k %100000*2%100000
所以要得到當前路徑%100000,取上一條路徑%100000的值乘2再取膜100000
但是因為儲存的是取過膜的數沒辦法比較大小,仔細分析後發現2^k永遠大於1+2^1+······+2^(k-1),後一條路會比前面所有路徑的總值還大,所以直接儲存這是第幾條路徑作為路徑標號,比較時等式兩邊的集合中的最大路徑標號所在方即為較大方,若相等比較次大的,這裡可以考慮用set儲存一下具體路徑。
(…)原本以為求最短路徑就是用dijskstra,可是寫到dijskstra的鬆弛操作發現居然是乙個最小生成樹的題。原因就是2^k永遠大於1+2^1+······+2^(k-1),那鬆弛的時候永遠選的是標號最小的那條,那直接從最小邊開始鬆弛,可以省去dijskstra的 d[y]與d[x]+w[x][y]路徑的大小判斷。於是在生產最小生成樹時,只要需要在合併根節點的時候就直接將整個圖更新一下就儲存了兩點間的最短路徑。
#include
#include
using
namespace
std;
#define maxn 101
#define maxm 501
#define maxw 100001
int edge[maxn][maxn];
int n,m;
int f[maxn];
int findf (int t)
void union(int x, int y)
int main()
for(int i = 0,dis = 1;i < m; i ++ )}}
union(x,y);
dis = dis * 2 % 100000 ;
}for(int i=1,root = findf(0); icout
<<"-1"
<0][i]<}
}
九度OJ題目1100 最短路徑
題目描述 n個城市,標號從0到n 1,m條道路,第k條道路 k從0開始 的長度為2 k,求編號為0的城市到其他城市的最短距離 輸入 第一行兩個正整數n 2 n 100 m m 500 表示有n個城市,m條道路 接下來m行兩個整數,表示相連的兩個城市的編號 輸出 n 1行,表示0號城市到其他城市的最短...
九度 1008 最短路徑問題
題目描述 給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。輸入 輸入n,m,點的編號是1 n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數 ...
九度oj 最短路徑問題
題目描述 給你n個點,m條無向邊,每條邊都有長度d和花費p,給你起點s終點t,要求輸出起點到終點的最短距離及其花費,如果最短距離有多條路線,則輸出花費最少的。輸入 輸入n,m,點的編號是1 n,然後是m行,每行4個數 a,b,d,p,表示a和b之間有一條邊,且其長度為d,花費為p。最後一行是兩個數 ...