牛客 十二橋問題 (最短路 狀態壓縮)

2022-03-17 03:44:23 字數 1855 閱讀 6217

小多所在的城市可以看成是有n個點m條邊的無向圖(結點從1標號),每條邊有乙個距離di,其中有k條邊是小希特別想走過的k座大橋。

小多和小希現在呆在1號結點,請你幫小多規劃一條最短路線,使得小多和小希能從當前位置出發,並經過這k座橋,最後回到結點1。

第一行輸入三個數n,m,k,分別表示結點數目,邊數和小希特別想走過的大橋數目。

隨後m行,第i行三個整數ui,vi,di表示從ui到vi有一條距離為di的邊。

其中前k條邊即為小希想去的大橋。

輸出一行,乙個整數,表示滿足條件的最短距離的路徑長度。

示例1輸入

3 4 2

2 3 5

2 2 10

1 2 1

3 1 4

輸出20

說明小希按線路1->2->2->3->1,分別花費1,10,5,4,共計20。

備註:對於100%的資料,整張圖聯通,di≤1000000000。

分析為什麼我覺得記錄牛客的題解像是在蹭熱度一般的罪惡

發現$k$還挺小的,所以考慮來一手全排列狀態壓縮,01表示一座橋是否走過

由於是最短長度,對於1號節點和所有橋的兩個端點都要求一次最短路

dp的時候可以不用管具體是怎麼走的,只管用最短路求出的路徑無腦轉移

雖然這樣可能會出現一些奇怪的轉移和狀態,但因為最優方案肯定是走最短路徑,所以我們一定會統計到最優方案的答案並把它存下來

但是如果直接壓縮進行$dp$,就不知道誰跟誰相連,更不知道當前狀態該怎麼去更新下乙個狀態

誰跟誰相連並不重要,重要的是應該知道當前的路徑末端是誰,所以$dp$狀態中應該加入當前的末端是誰

所以設$dp[i][s]$表示以1,i為兩個端點形成的走過邊的情況為s的鏈的最短長度,其中i為最後經過的那個橋的乙個端點

列舉最後走過的橋,下一座走過的橋,還有從哪個端點走到哪個端點,就可以轉移狀態了

感謝出題人不卡spfa

code

#include#include

#include

#include

using

namespace

std;

const

int maxn=50005

;const

int maxm=200005

;long

long d[maxn],dis[30][maxn],l[maxm][5];queueq;long

long dp[30][30005

],ans;

int n,m,k,ecnt,info[maxn],inq[maxn],nx[maxm<<1],v[maxm<<1],w[maxm<<1

];void add(int u1,int v1,int w1)

void spfa(int

x) }

}int

main()

memset(dp,

0x7f,sizeof dp);ans=dp[0][0

];

for(int i=1;i<=k;i++)for(int j=0;j<=1;j++)

int i=(1

<

);

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

for(int nw=1;nw)}}

for(int i=1;i<=k;i++)ans=min(ans,min(dp[i*2-1][i]+d[l[i][0]],dp[i*2][i]+d[l[i][1

]]));

printf(

"%lld\n

",ans);

}

牛客14369之最短路(SPFA模板)

簡單暴力的題目要求 給定乙個有n個頂點 從1到n編號 m條邊的有向圖 其中某些邊權可能為 負,但保證沒有負環 請你計算從1號點到其他點的最短路。第一行兩個整數n,m。接下來的m行,每行有三個整數u,v,l,表示u到v有一條長度為l的邊。共n 1行,第i行表示1號點到i 1號點的最短路。3 3 1 2...

牛客 D 炫酷路途(貪心 最短路)

題目描述 小希現在要從寢室趕到機房,路途可以按距離分為n段,第i個和i 1個是直接相連的,只需要一秒鐘就可以相互到達。炫酷的是,從第i個到第i 2 pi 2 p個也是直接相連的 其中p為任意非負整數 只需要一秒鐘就可以相互到達。更炫酷的是,有k個傳送法陣使得某些u,v之間也是直接相連的,只需要一秒鐘...

牛客網機試題 最短路徑(並查集)

n個城市,標號從0到n 1,m條道路,第k條道路 k從0開始 的長度為2 k,求編號為0的城市到其他城市的最短距離 第一行兩個正整數n 2 n 100 m m 500 表示有n個城市,m條道路 接下來m行兩個整數,表示相連的兩個城市的編號n 1行,表示0號城市到其他城市的最短路,如果無法到達,輸出 ...