可以發現\(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個人走的總距離最小 題...