ZJOI2011 營救皮卡丘

2022-08-13 14:18:16 字數 1795 閱讀 3001

似乎這玩意兒叫做\(k\)路徑覆蓋問題

可以發現\(k\)個人每個人走過的點集不相交

就是有\(n\)個點\(m\)條邊的圖,邊有邊權,從\(0\)出發,中途如果經過點\(u\),那麼之前必須經過點\(u-1\),可以從點\(s\)出發最多\(k\)次,問走到\(n\)的最小花費

那麼題目就轉化成了用不超過\(k\)條不相交的鏈覆蓋整張圖的最小代價

可以預處理出\(dis_\)表示從\(i\)走到\(j\),中途不經過\(>j\)的點的最短路徑

然後將每個點\(u\)都拆成兩個點\(u_1,u_2\)

\(s\to u_1\),流量為\(1\),費用為\(0\)

\(u_2\to t\),流量為\(1\),費用為\(0\)

\(u_1\to v_2[u,流量為1,費用為\(dis_\)

\(s\to 0\),流量為\(k\),費用為\(0\)

最小費用最大流即可

#include#include#include#include#includeconst int m = 405 ;

const int n = 100005 ;

const int inf = 1e9 ;

using namespace std ;

inline int read()

while(c>='0'&&c<='9')

return x*w ;

}bool exist[m] ;

int n , m , k , s , t , ans , num = 1 ;

int hea[m] , disp[m][m] , dis[m] , pre[m] ;

struct e edge[n] ;

inline void insert(int from , int to , int dis , int cst)

inline void add_edge(int u , int v , int w , int c)

queue < int > q ;

inline bool spfa() }}

return (pre[t] > 0) ;

}inline int mcmf()

return ans ;

}int main()

for(int k = 0 ; k <= n ; k ++)

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

for(int j = 0 ; j <= n ; j ++)

if(k <= i || k <= j)

disp[i][j] = min( disp[i][j] , disp[i][k] + disp[k][j] ) ;

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

add_edge(s , 0 , k , 0) ;

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

for(int u = 0 ; u < n ; u ++)

for(int v = u + 1 ; v <= n ; v ++)

if(disp[u][v] < inf)

add_edge(u , v + n , 1 , disp[u][v]) ;

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

return 0 ;

}

ZJOI2011 營救皮卡丘

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

ZJOI2011 營救皮卡丘

題目 題目鏈結 思路首先,看資料範圍比較小,想到網路流。對於最短路的那部分,在走到 j 的時候,不能經過 j 的點,所以在 floyd 的時候我們加一層限制 k j 處理出最短路。然後考慮網路流建邊。會發現有這麼幾個限制 從小的點走向大的點 每個點都必須走到 不得超過 k 條路徑 因為每一條路徑一定...

2324 ZJOI2011 營救皮卡丘

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