題面
神仙題。
做最小路徑覆蓋。
有乙個很像的地方,就是最小路徑覆蓋必須覆蓋到每個點,這道題也一樣。
這道題有4個和最小路徑覆蓋不一樣的地方
可以重複訪問(這個可以用$floyed$傳遞閉包解決)
每條路徑必須從原點出發
每個點必須被「到達」(並不能乙個節點成乙個路徑)
假設已經訪問了$1..x$,那麼至少有乙個人,它的訪問序列中第乙個比$x$大的元素為$x+1$
我們從第四點突破,假設已經訪問了$1..x$,那麼至少有乙個人$p_i$,它的訪問序列中第乙個比$x$大的元素為$x+1$,我們稱$p_i$擊破了$x+1$。
顯然,對於乙個合法的路徑覆蓋,乙個人的擊破序列是遞增的,且擊破序列中,每個點出現且僅出現一次。
那我們就直接對擊破序列做最小路徑覆蓋,$dis[i][j]$表示上乙個擊破的是$i$,這次要來擊破$j$了$(i但是這樣還不照,因為對於每個人,我們都需要支付它從$0$到第乙個擊破的點的費用,二分圖上,我們建$k$個新的$0$點,連得邊和老$0$點一樣的。在網路流中,就直接給$0$點流$k$即可。
這樣還是有問題,首先不能保證恰好是$k$條,其次不能保證$k$條都是每條對應乙個起點。
也很簡單。
$k$條都是每條對應乙個起點,因為起點之間沒有連邊,所以不可能有兩個起點在一起的。
總共$n+k$個點,只有最大流是$n$,則恰好就是$k$條,由霍爾定理,$y$部上面的$n$個點肯定飽和,下面$k$個點肯定匹配不到,所以最大流是$n$。
**
#include#include#include
#include
#include
#include
#include
#include
#define n 500
#define s 0
#define t (2*n+3)
#define ll long long
#define ri register int
#define inf 1000000007
using
namespace
std;
intn,m,k;
intdis[n][n];
struct
graph
bool
spfa()
}vis[x]=0
; }
return dis[t]}
int dfs(int x,int
lim)
}return
sum;
} ll zkw()
return
ret;
}} g;
intmain()
for (ri kk=0;kk<=n;kk++)
for (ri i=0;i<=n;i++)
for (ri j=0;j<=n;j++)
if (kk<=i || kk<=j) dis[i][j]=min(dis[i][j],dis[i][kk]+dis[kk][j]);
for (ri i=1;i<=n+1;i++)
for (ri j=i+1;j<=n+1;j++) if (i!=j) g.add_edge(i,n+1+j,1,dis[i-1][j-1
]); g.add_edge(s,
1,k,0
);
for (ri i=2;i<=n+1;i++) g.add_edge(s,i,1,0
);
for (ri i=n+2;i<=2*(n+1);i++) g.add_edge(i,t,1,0
); cout
}
ZJOI2011 營救皮卡丘
似乎這玩意兒叫做 k 路徑覆蓋問題 可以發現 k 個人每個人走過的點集不相交 就是有 n 個點 m 條邊的圖,邊有邊權,從 0 出發,中途如果經過點 u 那麼之前必須經過點 u 1 可以從點 s 出發最多 k 次,問走到 n 的最小花費 那麼題目就轉化成了用不超過 k 條不相交的鏈覆蓋整張圖的最小代...
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個人走的總距離最小 題...