HDU6094 Rikka with K-Match
Posted autoint
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU6094 Rikka with K-Match相关的知识,希望对你有一定的参考价值。
Rikka with K-Match
Yuta has a graph (G) with (n) nodes ((i,j)(1 leq i leq n,1 leq j leq m)). There is an edge between ((a,b)) and ((c,d)) if and only if (|a-c|+|b-d|=1). Each edge has its weight.
Now Yuta wants to calculate the minimum weight (K)-matching of (G).
(1 leq n leq 4 imes 10^4,1 leq m leq 4)
题解
https://blog.csdn.net/The_star_is_at/article/details/76919415
应该是一个经典的 Idea 了。令 (w_i) 为匹配数为 (i) 时的最小匹配,那么因为匹配是一个费用流问题,所以一定有 (w_{i+1}-w_{i} geq w_{i}-w_{i-1})。
考虑把 (w_i) 看成平面上的点 ((i,w_i)),那么显然所有点都分布在一个下凸壳上,因此肯定存在一个斜率 (d),使得这个斜率的直线与下凸壳的切点恰好为 ((K,w_K)),即 ((K,w_K)) 为 (w_i-id) 最小的点,这相当于把边权减去 (d) 后的最小匹配。
因此可以二分斜率 (d),然后求出边权全部减去 (d) 后的最小匹配的值以及最小匹配中有多少条边,根据最小匹配中的边数和 (K) 的大小关系来决定二分的方向。这样问题就转化成了求 (O(log n)) 次网格图最大匹配。这是一个轮廓线 DP 的经典问题,可以在 (O(nm2^m)) 内解决。
因此总的时间复杂度为 (O(nm2^mlog n))。
要注意的是二分上界不能设为 (10^9) 级别,考虑一条 (1) 和 (10^9) 交错的链,那么在最后一次增广的时候所有的 (1) 都会变成 (10^9),因此二分上界应该是 (10^9 imes frac{nm}{2}),标程把上界设为了 (10^{14}),DP 时刚好不会爆 long long
。
CO int64 inf=1e18;
int n,m,A[40001][4],B[40001][4];
int64 f[2][5][1<<4];int g[2][5][1<<4];
pair<int64,int> solve(int64 mid){
for(int i=0;i<=m;++i) fill(f[0][i],f[0][i]+(1<<m),inf);
f[0][m][(1<<m)-1]=g[0][m][(1<<m)-1]=0;
int o=1;
for(int u=1;u<=n;++u){
for(int i=0;i<=m;++i) fill(f[o][i],f[o][i]+(1<<m),inf);
copy(f[o^1][m],f[o^1][m]+(1<<m),f[o][0]);
copy(g[o^1][m],g[o^1][m]+(1<<m),g[o][0]);
for(int i=0;i<m;++i)for(int s=0;s<1<<m;++s){
if(i<m-1){
int t=s|1<<i|1<<(i+1);
int64 v=f[o][i][s]+B[u][i]-mid;
int c=g[o][i][s]+1;
if(f[o][i+2][t]>v or (f[o][i+2][t]==v and g[o][i+2][t]<c))
f[o][i+2][t]=v,g[o][i+2][t]=c;
}
if(u>1 and ~s>>i&1){
int t=s|1<<i;
int64 v=f[o][i][s]+A[u-1][i]-mid;
int c=g[o][i][s]+1;
if(f[o][i+1][t]>v or (f[o][i+1][t]==v and g[o][i+1][t]<c))
f[o][i+1][t]=v,g[o][i+1][t]=c;
}
int t=s&~(1<<i);
int64 v=f[o][i][s];
int c=g[o][i][s];
if(f[o][i+1][t]>v or (f[o][i+1][t]==v and g[o][i+1][t]<c))
f[o][i+1][t]=v,g[o][i+1][t]=c;
}
o^=1;
}
int64 ans=inf;int K=0;
for(int s=0;s<1<<m;++s)
if(ans>f[o^1][m][s] or (ans==f[o^1][m][s] and K<g[o^1][m][s]))
ans=f[o^1][m][s],K=g[o^1][m][s];
return make_pair(ans,K);
}
void real_main(){
read(n),read(m);
int K=read<int>();
for(int i=1;i<n;++i)for(int j=0;j<m;++j) read(A[i][j]);
for(int i=1;i<=n;++i)for(int j=0;j<m-1;++j) read(B[i][j]);
int64 l=0,r=1e14;
while(l<r){
int64 mid=(l+r)>>1;
if(solve(mid).second>=K) r=mid;
else l=mid+1;
}
printf("%lld
",solve(l).first+l*K);
}
int main(){
for(int T=read<int>();T--;) real_main();
return 0;
}
以上是关于HDU6094 Rikka with K-Match的主要内容,如果未能解决你的问题,请参考以下文章
HDU 6095: Rikka with Competition