ZJOI2011 營救皮卡丘

2022-09-11 00:39:34 字數 1247 閱讀 7357

題目

題目鏈結

思路首先,看資料範圍比較小,想到網路流。

對於最短路的那部分,在走到\(j\)的時候,不能經過\(>j\)的點,所以在\(floyd\)的時候我們加一層限制\(k<=j\)處理出最短路。

然後考慮網路流建邊。會發現有這麼幾個限制:

從小的點走向大的點

每個點都必須走到

不得超過\(k\)條路徑

因為每一條路徑一定都是從較小的點走向較大的點的,所以其實這是乙個\(dag\)。

然後考慮如何在建圖中體現這些性質:

這個貌似叫作最小路徑覆蓋問題。

把每個點拆成入點和出點。

將\(s\)和\(0\)的出點連邊,流量設為\(k\),表示一開始有\(k\)個人從\(0\)點出發。

將每條路徑的起點的入點向終點的出點連一條流量為\(1\)的邊。

將每個點的出點向\(t\)連一條流量為\(1\)的邊。

將\(s\)到每乙個點的出點連一條容量為\(1\)的邊。

這樣為什麼就是對的呢?筆者一開始看見這個建圖也是一臉懵逼。

不妨換乙個角度想:

每一條邊都是一定要經過的。

也就是說每一條邊都要有人去走。

至於是誰走的我們並不關心。

所以將人放在點上,再連邊讓其」走出去「

這樣建圖的目的只是為了讓最大流為\(n\),保證皮卡丘最終得救。

**

#include#define m 305

using namespace std;

const int inf=1e9;

int n,m,k,s,t,tt=1,h[m];

int dis[m][m];

void floyd()}}

}return ds[t]!=inf;

}int ans=0,ans2=0;

void update()

}int main()

floyd();

s=0,t=2*n+1;

add(s,1,k,0);

for(int i=2;i<=n;i++)

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

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

if(dis[i][j]<1e9)

add(i,j+n,1,dis[i][j]);

while(spfa())update();

printf("%d\n",ans2);

return 0;

}

ZJOI2011 營救皮卡丘

題面 神仙題。做最小路徑覆蓋。有乙個很像的地方,就是最小路徑覆蓋必須覆蓋到每個點,這道題也一樣。這道題有4個和最小路徑覆蓋不一樣的地方 可以重複訪問 這個可以用 floyed 傳遞閉包解決 每條路徑必須從原點出發 每個點必須被 到達 並不能乙個節點成乙個路徑 假設已經訪問了 1.x 那麼至少有乙個人...

ZJOI2011 營救皮卡丘

似乎這玩意兒叫做 k 路徑覆蓋問題 可以發現 k 個人每個人走過的點集不相交 就是有 n 個點 m 條邊的圖,邊有邊權,從 0 出發,中途如果經過點 u 那麼之前必須經過點 u 1 可以從點 s 出發最多 k 次,問走到 n 的最小花費 那麼題目就轉化成了用不超過 k 條不相交的鏈覆蓋整張圖的最小代...

2324 ZJOI2011 營救皮卡丘

題目鏈結 題目大意 n 1個城市 0到n 初始時k個人都在0城市。城市之間有距離。要求 1 遍歷完n個城市 有乙個人遍歷了某個城市就算這個城市被遍歷了 2 遍歷i城市前必須遍歷完前i 1個城 市,並且在遍歷前i 1個城市時不能經過大於等於i的城市。在滿足 1 2 的前提下使得k個人走的總距離最小 題...