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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

POJ 3613 快速幂+Floyd变形(求限制k条路径的最短路)

發布時間:2025/6/17 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 POJ 3613 快速幂+Floyd变形(求限制k条路径的最短路) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
? ? ? 給你一個無向圖,然后給了一個起點s和終點e,然后問從s到e的最短路是多少,中途有一個限制,那就是必須走k條邊,路徑可以反復走。

思路:
? ? ? 感覺很贊的一個題目,據說證明是什么國家隊集訓隊論文什么的,自己沒去看那個論文,就說下我自己的理解吧,對于這個題目,我們首先分析下Floyd,那個算法的過程中是在更新的dis[i][j]上再更新,再更新。。。,是想一下,我們每次都把更新的結果存下來,就是每次答案數組初始化全是INF,然后用當前的dis數組和原始的map來更新,那么更新得到的就應該是dis的狀態下在多走一條邊到達各個點的最短,就這樣,想得到第幾條邊的最短路就更新幾次就行了,只要結構如下

??

? now初始化INF

? for(int k = 1 ;k <= n ;k ++)
? for(int i = 1 ;i <= n ;i ++)
? for(int j = 1 ;j <= n ;j ++)
? now[i][j] = min(now[i][j] ,dis[i][k] + map[k][j]);
dis是上一步的now,map是原始的圖,有點dp的意思,如果不理解可以這樣寫


now初始化INF
? for(int i = 1 ;i <= n ;i ++)
? for(int j = 1 ;j <= n ;j ++)
? for(int k = 1 ;k <= n ;k ++)
? now[i][j] = min(now[i][j] ,dis[i][k] + map[k][j]);

這樣就方便理解了,就是在原來的基礎上在多加(強制)一條邊去更新,不要感覺說Floyd的三重for循環不能調換這里面就不能調換,其實這里面的根本不是Floyd我們要的只是在加一條邊更新所有,所以怎么寫都行,然后就是這個題目的另一個關鍵,如果直接就寫估計會超時,這是我們可以用類似矩陣快速冪的方式去優化,如果用到快速冪就要證明a^b = a^2(b/2)這個地方我不能說太多,因為怕說錯了,我只是感覺因為這個題目的過程滿足結合律,所以滿足上面的那個式子,具體的就看下面代碼吧。



#include<stdio.h> #include<string.h>#define N 220 #define INF 1000000000typedef struct {int mat[N][N]; }A;int mark[1100];int minn(int x, int y) {return x < y ? x : y; }A Floyd (A a ,A b ,int n) {A c;for(int i = 1 ;i <= n ;i ++)for(int j = 1 ;j <= n ;j ++)c.mat[i][j] = INF;//這個地方看好了,是初始化成INF,不是平時的Floyd直接就在更新的數組上在更新。for(int k = 1 ;k <= n ;k ++)for(int i = 1 ;i <= n ;i ++)for(int j = 1 ;j <= n ;j ++)//for(int k = 1 ;k <= n ;k ++)c.mat[i][j] = minn(c.mat[i][j] ,a.mat[i][k] + b.mat[k][j]);return c; }A Qpow_Mat(A a ,int b ,int n) {A c;int mk = 0;while(b){if(b & 1) {!mk ? c = a : c = Floyd(c ,a ,n);mk = 1;}b >>= 1;a = Floyd(a ,a ,n);}return c; }int main () {int n ,t ,s ,e ,i ,j ,a ,b ,c ,nowid;A Ans;scanf("%d %d %d %d" ,&n ,&t ,&s ,&e);{memset(Ans.mat ,255 ,sizeof(Ans.mat));memset(mark ,0 ,sizeof(mark)) ,nowid = 0;for(i = 1 ;i <= t ;i ++){scanf("%d %d %d" ,&c ,&a ,&b);if(!mark[a]) mark[a] = ++nowid;if(!mark[b]) mark[b] = ++nowid;a = mark[a] ,b = mark[b];Ans.mat[a][b] = Ans.mat[b][a] = c;}for(i = 1 ;i <= nowid ;i ++)for(j = 1 ;j <= nowid ;j ++)if(Ans.mat[i][j] == -1) Ans.mat[i][j] = INF;Ans = Qpow_Mat(Ans ,n ,nowid);printf("%d\n" ,Ans.mat[mark[s]][mark[e]]);}return 0; }

總結

以上是生活随笔為你收集整理的POJ 3613 快速幂+Floyd变形(求限制k条路径的最短路)的全部內容,希望文章能夠幫你解決所遇到的問題。

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