zoukankan      html  css  js  c++  java
  • @codeforces


    @description@

    给定一个 n 点 m 边的图,边有边权,点有点权。

    找到一个连通的诱导子图(选中的点之间的边必须选,选中的边的端点必须选),使得这个子图的密度最大。
    密度的定义为:如果边权和为 0,则密度 = 0;否则密度 = 点权和 / 边权和。

    Input
    第一行两个空格隔开的整数 n (1 ≤ n ≤ 500), m (1 ≤ m ≤ n*(n-1)/2)。
    第二行 n 个空格隔开的整数 xi (1 ≤ xi ≤ 10^6),表示每个点的点权。
    接下来 m 行,每行三个空格隔开的整数 ai, bi, ci (1 ≤ ai < bi ≤ n; 1 ≤ ci ≤ 10^3),描述了一条边。保证没有重边。

    Output
    输出一个实数表示答案。

    Examples
    Input
    1 0
    1
    Output
    0.000000000000000

    Input
    2 1
    1 2
    1 2 1
    Output
    3.000000000000000

    @solution@

    一看还以为是什么 01 分数规划 + 最大闭合权子图。。。

    注意这个密度的定义很像平均值,而平均值最值还有另一个解法:min{a, b} <= a 与 b 的平均值 <= max{a, b}。
    也就是说最优情况一定只取单个元素。

    套个这个题上面,大胆猜测只取一条边最优。

    感性证明一下。假如一条边对应的端点点权和为 ai,边权为 bi。
    首先有 max{ai/bi, aj/bj} >= (ai + aj)/(bi + bj),可以反证。
    那么一个包含多条边的图,对应的密度 (∑ai - delta)/∑bi <= ∑ai/∑bi <= max{ai/bi}。其中 delta 是算重复的点权。

    @accepted code@

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int MAXN = 500;
    double x[MAXN + 5], ans;
    int main() {
    	int n, m; scanf("%d%d", &n, &m);
    	for(int i=1;i<=n;i++) scanf("%lf", &x[i]);
    	for(int i=1;i<=m;i++) {
    		int a, b; double c; scanf("%d%d%lf", &a, &b, &c);
    		ans = max(ans, (x[a] + x[b]) / c);
    	}
    	printf("%.9f
    ", ans);
    }
    

    @details@

    偶尔切一切小清新的结论题还是挺开心的~
    话说这个比赛场次。。。第 444 场。。。

  • 相关阅读:
    搭建AngualarJS开发环境
    博客从博客园迁移到github上
    探讨Android中的内置浏览器和Chrome
    Netbeans配置Xdebug
    关于 Xcode 调试工具 GDB and LLDB
    关于ios 运行时 介绍的比较详细的帖子
    你不知道的KVO的内部实现
    sqlite 判断表中是否包含 某个字段
    发一些靠谱的招聘网站(含ios)
    解析 友盟崩溃信息
  • 原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/11852054.html
Copyright © 2011-2022 走看看