• [洛谷P1642]规划


    题目大意:有一棵$n(nleqslant100)$个点的树,每个点有两个权值$a,b$,要求选择一个$m$个点的连通块$S$,最大化$dfrac{sumlimits_{iin S}a_i}{sumlimits_{iin S}b_i}$

    题解:$01$分数规划,这一类的问题可以二分答案来做,二分这个值,然后把第$i$个点的权值变为$a_i-b_imid$,跑一遍树形$DP$,$f_{i,j}$表示以第$i$个点为根,连通块大小为$j$的最大值。看答案是否大于$0$,是则把答案变大,否则缩小答案

    卡点:做背包时做反了,$01$背包变成完全背包,精度不够。

    C++ Code:

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #define maxn 111
    const double eps = 1e-3;
    
    int head[maxn], cnt;
    struct Edge {
    	int to, nxt;
    } e[maxn << 1];
    inline void addedge(int a, int b) {
    	e[++cnt] = (Edge) { b, head[a] }; head[a] = cnt;
    	e[++cnt] = (Edge) { a, head[b] }; head[b] = cnt;
    }
    
    int n, m;
    int a[maxn], b[maxn];
    double w[maxn], f[maxn][maxn], res;
    
    inline void chkmax(double &a, double b) { if (a < b) a = b; }
    void dfs(int u, int fa = 0) {
    	f[u][0] = 0, f[u][1] = w[u];
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (v != fa) {
    			dfs(v, u);
    			for (int j = m; j; --j)
    				for (int k = 0; k < j; ++k)
    					chkmax(f[u][j], f[u][j - k] + f[v][k]);
    		}
    	}
    	chkmax(res, f[u][m]);
    }
    int main() {
    	scanf("%d%d", &n, &m); m = n - m;
    	for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    	for (int i = 1; i <= n; ++i) scanf("%d", b + i);
    	for (int i = 1, a, b; i < n; ++i) {
    		scanf("%d%d", &a, &b);
    		addedge(a, b);
    	}
    	double l = 0, r = 10000;
    	while (l + eps < r) {
    		const double mid = (l + r) / 2;
    		memset(f, 0xc2, sizeof f); res = **f;
    		for (int i = 1; i <= n; ++i) w[i] = a[i] - b[i] * mid;
    		dfs(1);
    		if (res >= 0) l = mid;
    		else r = mid;
    	}
    	printf("%.1lf
    ", l);
    	return 0;
    }
    

      

  • 相关阅读:
    代码重构(转)
    Apache负载均衡 配置
    恒久的忍耐
    setInterval全面的介绍
    引用 110个Oracle 常用函数的总结
    ssl和tls
    JSTL
    java异常处理的陋习(转载)
    Java 6 JVM参数选项大全(中文版)
    liunx基础常用命令
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10352798.html
Copyright © 2020-2023  润新知