规划
题目链接:https://www.luogu.com.cn/problem/P1642
题解:
分数规划,设
d
[
i
]
=
a
[
i
]
−
m
i
d
∗
b
[
i
]
d[i] = a[i]-mid*b[i]
d[i]=a[i]−mid∗b[i].
check:动态规划,求是否存在m个点连通块
d
[
i
]
d[i]
d[i]。
d
p
[
u
]
[
i
]
dp[u][i]
dp[u][i]代表以
u
u
u为根节点的子树,选
i
i
i个节点能得到的最大的
d
[
i
]
d[i]
d[i]和。
递推方程
d
p
[
u
]
[
j
+
k
]
=
m
a
x
(
d
p
[
u
]
[
j
+
k
]
,
d
p
[
u
]
[
j
]
+
d
p
[
v
]
[
k
]
)
(
1
≤
j
≤
s
z
[
u
]
,
0
≤
k
≤
s
z
[
v
]
)
dp[u][j+k] = max(dp[u][j+k], dp[u][j]+dp[v][k])(1\le j \le sz[u],0\le k \le sz[v])
dp[u][j+k]=max(dp[u][j+k],dp[u][j]+dp[v][k])(1≤j≤sz[u],0≤k≤sz[v])。
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 120;
const int mod = 10000;
int a[maxn], b[maxn], sz[maxn];
double d[maxn], dp[maxn][maxn], tmp[maxn];
vector<int> g[maxn];
bool check(int n, int m);
void dfs(int u, int f, int m);
int main()
{
int n, m, i, j, k;
double l, r;
scanf("%d %d", &n, &m);
m = n-m;
for(i=1;i<=n;i++)
scanf("%d", &a[i]);
for(i=1;i<=n;i++)
scanf("%d", &b[i]);
for(i=1;i<n;i++){
scanf("%d %d", &j, &k);
g[j].push_back(k);
g[k].push_back(j);
}
l = 0, r = 1e12;
while(l+eps<r)
{
double mid = (l+r)/2;
for(i=1;i<=n;i++)
d[i] = a[i] - mid*b[i];
if(check(n, m))l = mid;
else r = mid;
}
printf("%.1f\n", l);
return 0;
}
bool check(int n, int m)
{
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
dp[i][j] = -1e8;
dfs(1, 0, m);
for(int i=1;i<=n;i++)
if(dp[i][m] >= 0.0)return true;
return false;
}
void dfs(int u, int f, int m)
{
sz[u] = 1;
dp[u][0] = 0;
dp[u][1] = d[u];
for(int i=0;i<g[u].size();i++){
int v = g[u][i];
if(v == f)continue;
dfs(v, u, m);
for(int j=0;j<=m;j++)
tmp[j] = dp[u][j];
//因为当前的根节点必选,所以j从1开始
for(int j=1;j<=sz[u];j++)
for(int k=0;k<=sz[v];k++)
if(j+k<=m)
tmp[j+k] = max(tmp[j+k], dp[u][j]+dp[v][k]);
for(int j=0;j<=m;j++)dp[u][j] = tmp[j];
sz[u] += sz[v];
}
}