relays 奶牛接力跑(矩陣快速冪求最短路徑)

2022-03-26 21:05:47 字數 1739 閱讀 4067

題幹:

fj的n(2<=n<=1,000,000)頭奶牛選擇了接力跑作為她們的日常鍛鍊專案。至於進行接力跑的地點 自然是在牧場中現有的t(2 <= t <= 100)條跑道上。農場上的跑道有一些交匯點,每條跑道都鏈結了兩個不同的交匯點 i1_i和i2_i(1<=i1_i<=1,000; 1<=i2_i<=1,000)。每個交匯點都是至少兩條跑道的端點。 奶牛們知道每條跑道的長度length_i(1<=length_i<=1,000),以及每條跑道鏈結的交匯點的編號 並且,沒有哪兩個交匯點由兩條不同的跑道直接相連。你可以認為這些交匯點和跑道構成了一張圖。 為了完成一場接力跑,所有n頭奶牛在跑步開始之前都要站在某個交匯點上(有些交匯點上可能站著不只1頭奶牛)。當然,她們的站位要保證她們能夠將接力棒順次傳遞,並且最後持棒的奶牛要停在預設的終點。 你的任務是,寫乙個程式,計算在接力跑的起點(s)和終點(e)確定的情況下,奶牛們跑步路徑可能的最小總長度。顯然,這條路徑必須恰好經過n條跑道。

題解:

看到 n 這麼大嚇了一跳,最後看到 n 其實就是路徑長度,基本上這就是矩陣快速冪了。但是節點大小為1~1000,顯然難以承受,但是它的邊不過 100 條,所以它有用的點最多為 101 個(連通),通過離散化可以實現(或者先建邊,dfs一遍標個號即可)。將路徑長度作為指數,直接將每個邊的長度作為矩陣的值進行矩陣快速冪。

為什麼要將將每個邊的長度直接作為矩陣的值?不用縮點嗎?若我們進行縮點,100000 個點一定無法接受。再者,其實若是求必經 n 條路的最短路徑長度,我們矩陣的定義就變為了由 x 到 y 節點必須經過 z 條路徑的最小值,而每個節點的值就是路徑長度,所以不需縮點。

但是如果是普通的矩陣快速冪,它求出的只是經過乙個點的路徑種類數,無法滿足我們的預期,我們可以將矩陣乘法由題意改變一下,變為:

sum.a[i][j]=min(sum.a[i][j],aa.a[i][k]+bb.a[k][j]);

可以發現,把矩陣乘法的 ∑ 改成取 min 一樣滿足分配律;而且矩陣乘幾次,它每個點所表示的就變為了恰好經過 n 的長度(可以走重邊)到達這個點(座標)的方案總數。(本題就是最短距離)所以我們是可以將矩陣乘法變為我們所需要的形式。

code:

1 #include2 #include3 #include4

#define $ 111

5using

namespace

std;

6int m,n,t,start,done,in[$],sta[$*2],out

[$],w[$],up;

7 inline int min(int x,int y)

8struct

tree

11 friend tree operator *(tree aa,tree bb)

19 friend tree operator ^ (tree aa,int

x)25

};26

signed main()

39 start=lower_bound(sta+1,sta+m+1,start)-sta;

40 done= lower_bound(sta+1,sta+m+1,done)-sta;

41 ans=ans^n;

42 printf("

%d\n

",ans.a[start][done]);

43 }

view code

矩陣快速求冪

今天看 劍指offer 看到乙個遞推關係 f n f n 1 f n 2 書中提出了一種簡單的演算法,也就是矩陣乘法 如果是n次方,那麼時間複雜度應該是o n 那麼有沒有一種更快的演算法呢?快速冪演算法能讓時間複雜度降至o logn 怎麼來做快速冪演算法呢?我們首先先想乙個簡單的,乙個數字a,求他的...

矩陣快速求冪

在只使用標準庫的情況下,c 沒有現成的處理矩陣的標準庫,所以矩陣的運算就比較麻煩,尤其是矩陣的乘法 加減法都可以對應位置做加減,乘法的運算相對比較複雜,冪運算又會帶來的大量的乘法運算,所以這裡記錄一種 矩陣快速求冪的方法。這種方法可以將運算降低至指數次,原理是這樣的 1.矩陣a的m次方,先把m分解成...

矩陣快速冪求fib

qn是個特別可愛的小哥哥,qy是個特別好的小姐姐,他們兩個是一對好朋友 cp 劃掉 又是一年嚶花爛漫時,小qn於是就邀請了qy去嚶花盛開的地方去玩。當qy和qn來到了田野裡時,qy驚奇的發現,嚶花花瓣以肉眼可見的速度從樹上長了出來。仔細看看的話,花瓣實際上是以一定規律長出來的,而且,每次張成新的花瓣...