1. 程式人生 > >【[USACO09DEC]牛收費路徑Cow Toll Paths】

【[USACO09DEC]牛收費路徑Cow Toll Paths】

很妙的一道題,我之前一直是用一個非常暴力的做法

就是列舉點權跑堆優化dijkstra

但是詢問次數太多了

於是一直只有50分

今天終於做了這道題,不貼程式碼了,只說一下對這道題的理解

首先點權和邊權不能混在一起,這是公認的,畢竟這個樣子完全沒有辦法處理

那我們為什麼要排序呢,發現其餘幾篇題解好像也沒講清楚

說得好像我能講清楚一樣

我們對於所有點按點權進行了一個排序,這一點很令人玩味,這是為什麼呢

首先我們的floyd的列舉是長這個樣子的

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

最外層列舉的\(k\)是列舉的什麼

中轉點啊

那我們排序完了之後說明什麼

說明我們中轉點加入的順序是從小到大的

於是我們在找\(i\),\(j\)之間的最短路的時候,我們的中轉點如果只是列舉到了\(k1\)

那麼這又說明了什麼

這說明了我們當前的\(i\),\(j\)之間的最短路中並沒有點權超過\(k1\)的點

於是當前這條最短路上除去起點和終點點權最大的也就是\(k1\)

那麼我們就可以這樣更新了

dist[i][j]=min(dist[i][j],d[i][j]+max(nm[k].d,max(nm[i].d,nm[j].d)))

這是從樓下的那位大佬程式碼裡抄來的

怎麼說呢

我們當前的k越大,說明我們的最短路中可能的中轉點越多,最短路也就越短(儘管可能隨著\(k\)增大最短路並不會變短,而是不變),但是同時我們加入的中轉點的點權也越來越大

也就是說我們每次新加入一箇中轉點,可能最短路是變短了,但是我們的點權最大值也增加了,這個時候就要與前面的dist值取一個最小了

於是程式碼就不貼了