嘟嘟嘟

看到最后让求一个比值,应该得往01规划上去想。令x = ∑v[i] / ∑c[i],则x * ∑c[i] = ∑v[i], ∑(v[i] - x * c[i]) = 0.

于是可以二分x(注意是实数二分),每一个点得到新的权值v[i] - mid * c[i],然后树上背包求最大值。如果最大值>0,说明x取消了,向[mid, R]二分;否则说明x取大了,向[L, mid]二分。

这个树上背包是比较经典的:求树上一个n - m的连通块,使块中的点的权值之和最大。

令dp[u][j]表示以u为根的子树中,有一个点数为 j 的联通块时的最大值。这个联通块一定是包含u的,否则就无法转移。然后就是相三层循环那样dp就行了(不过经过证明树上背包复杂度是O(n2)的)。

所以总复杂度O(n2logn)。

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define rg register
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch)) {ans = ans * + ch - ''; ch = getchar();}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) x = -x, putchar('-');
if(x >= ) write(x / );
putchar(x % + '');
} int n, m;
struct Edge
{
int to, nxt;
}e[maxn << ];
int head[maxn], ecnt = ;
void addEdge(int x, int y)
{
e[++ecnt].to = y;
e[ecnt].nxt = head[x];
head[x] = ecnt;
} int v[maxn], c[maxn];
db val[maxn], dp[maxn][maxn]; int siz[maxn];
void dfs(int now, int fa)
{
siz[now] = ;
dp[now][] = ;
for(int i = head[now]; i; i = e[i].nxt)
{
if(e[i].to == fa) continue;
dfs(e[i].to, now);
siz[now] += siz[e[i].to];
for(int j = min(m, siz[now]); j >= ; --j)
for(int k = ; k <= min(j, siz[e[i].to]); ++k)
dp[now][j] = max(dp[now][j], dp[now][j - k] + dp[e[i].to][k]);
}
for(int i = min(m, siz[now]); i > ; --i)
dp[now][i] = dp[now][i - ] + val[now];
} bool judge(db x)
{
for(int i = ; i <= n; ++i)
for(int j = ; j <= m; ++j) dp[i][j] = -INF;
for(int i = ; i <= n; ++i) val[i] = (db)v[i] - x * (db)c[i];
dfs(, );
for(int i = ; i <= n; ++i)
if(dp[i][m] > -eps) return ;
return ;
} int main()
{
n = read(); m = read();
m = n - m;
for(int i = ; i <= n; ++i) v[i] = read();
for(int i = ; i <= n; ++i) c[i] = read();
for(int i = ; i < n; ++i)
{
int x = read(), y = read();
addEdge(x, y); addEdge(y, x);
}
db L = , R = 1e6;
while(R - L > eps)
{
db mid = (L + R) / 2.00;
if(judge(mid)) L = mid;
else R = mid;
}
printf("%.1lf\n", L);
return ;
}

luogu P1642 规划的更多相关文章

  1. P1642 规划

    题目链接 题意分析 一看就知道是一道\(01\)分数规划的题 我们二分值之后 跑树形背包就可以了 CODE: #include<iostream> #include<cstdio&g ...

  2. [洛谷P1642]规划

    题目大意:有一棵$n(n\leqslant100)$个点的树,每个点有两个权值$a,b$,要求选择一个$m$个点的连通块$S$,最大化$\dfrac{\sum\limits_{i\in S}a_i}{ ...

  3. P1642 规划 01分数规划+树形DP

    $ \color{#0066ff}{ 题目描述 }$ 某地方有N个工厂,有N-1条路连接它们,且它们两两都可达.每个工厂都有一个产量值和一个污染值.现在工厂要进行规划,拆除其中的M个工厂,使得剩下的工 ...

  4. P1642 规划 [01分数规划]

    裸题,考虑size完了跑一个树上背包,这题没了. // by Isaunoya #include <bits/stdc++.h> using namespace std; #define ...

  5. BZOJ 4819 Luogu P3705 [SDOI2017]新生舞会 (最大费用最大流、二分、分数规划)

    现在怎么做的题都这么水了.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=4819 (luogu) https://ww ...

  6. luogu 4377 Talent show 01分数规划+背包dp

    01分数规划+背包dp 将分式下面的部分向右边挪过去,通过二分答案验证, 注意二分答案中如果验证的mid是int那么l=mid+1,r=mid-1,double类型中r=mid,l=mid; 背包dp ...

  7. luogu 2115 破坏(01分数规划)

    题意:给出一个序列,删除一个连续的子串后使得剩下的平均值最小. 典型的01分数规划,令f(x)=(sum1[i]+sum2[j])/(i+j).sum1表示前缀和,sum2表示后缀和,那么我们就相当于 ...

  8. Luogu P1768 天路 0/1分数规划+dfs spfa

    “那是一条神奇的天路诶~~把第一个神犇送上天堂” 怕不是某大佬早就A了这题,然鹅我又调了很久很久... 好吧就是0/1分数规划,但是跑的dfs的spfa(好像题解说bfs过不了????不知) 发现把s ...

  9. 【Luogu】P3705新生舞会(费用流+分数规划+二分答案)

    题目链接 本来以为自己可以做出来,结果……打脸了 (貌似来wc立了好几个flag了,都没竖起来) 不过乱蒙能蒙出一个叫“分数规划”的东西的式子还是很开心的 观察$C=\frac{a_{1}+a_{2} ...

随机推荐

  1. js事件绑定简单写法

    $E.on = function (o, e, f) { return o.addEventListener ? o.addEventListener(e, f, false) : o.attachE ...

  2. C#把大写英文变成小写英文,把小写英文变成大写英文

    static void Main(string[] args) { string s;  // 声明一个变量,来接受用户输入的值. Console.WriteLine("请输入一个字符串:& ...

  3. linux修改用户名和密码

    linux修改用户名和密码 修改root密码:sudo passwd root 修改用户密码(如hadoop) sudo passwd hadoop 修改主机名:sudo vi /etc/hostna ...

  4. idea快捷键、常用设置

      代码提示: code completion :ALT + / 选用Eclipse的keymap. 设置代码助手快捷键(keymap-basic) 代码上下行复制(Ctrl + Alt + Down ...

  5. 使用js获取URL地址栏里面的参数, 获取请求链接参数,函数定义如下

    function getUrlRequestParam(name) { var paramUrl = window.location.search.substr(1); var paramStrs = ...

  6. Spring课程 Spring入门篇 6-2 ProxyFactoryBean及相关内容(上)

    1 解析 1.1 类的方式实现各种通知需要实现的接口 1.2 创建Spring aop代理的优点及方法 1.3 代理控制切入点和通知的顺序的代码实现(具体完全实现,见代码2.1) 1.4 代理方式选择 ...

  7. php编程--二叉树遍历算法实现

    今天使用php来实现二叉树的遍历 创建的二叉树如下图所示 php代码如下所示:   <?php   class Node {   public $value;   public $child_l ...

  8. easyui扩展行默认展开 以及 去除滚动条

     问题背景: 在做打印页面的时候,要求有详细的默认展开显示.    遇到的问题: 1)在用扩展行的时候,grid的所有行都添加了展开收起的图标,(第二行没有明细)如下  2)默认展示有详细行的时候,内 ...

  9. 关联函数 map 的基本用法

    1.map简介 map是一类关联式容器.它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响.对于迭代器来说,可以修改实值,而不能修改key. 2.map的功能 自 ...

  10. According to TLD, tag fmt:formatDate must be empty, but is not 问题的解决

    在执行jsp格式化后报错,检查下代码,发现变成如下的样式: <fmt:formatDate value="${cur.sa_date}" pattern="yyyy ...