zoukankan      html  css  js  c++  java
  • CF1401D Maximum Distributed Tree

    原题链接

    • 题意:(f(i, j)) 代表了从 (i)(j) 的简单路径边权和。要求构造给定树的边权使得 (sum_{i=1}^{n} sum_{j = i}^{n}f(i, j)) 最大。
    • 题解:设一条边为 (<u, v>) 然后设 (cnt_u) 为节点 (u) 的子节点的数量,首先自己想到的就是 (dfs) 处理一遍就行。可知每条边的权重对答案贡献为 (cnt_u imes cnt_v imes w_e),然后分配 (m) 个质数给 (w) 就行了。但是很显然如果质数数量小于 (n) 那么就是直接用大的向小的给他们乘。然后如果素数数量大于 (n-1) 那么就考虑如何搞,假设把大的给大的乘,然后,设 (k_1,k_2,k_3) 为素数,且 (k_1 > k_2 > k_3) 并且 (sum_1 > sum_2 > sum_3)。得出不等式:

    [k_1 imes k_3 imes sum_1 + k_2 imes sum_2 < k_1 imes k_2 imes sum_1 + k_3 imes sum_2 ]

    [k_1 imes sum_1 imes(k_3 - k_2) < sum_2 imes(k_2 - k_3) ]

    很显然 (k_3 > k_2)等式左边小于零,右边大于零,所以等式成立。
    所以以后贪心最好用不等式证明一下正确性。

    • 代码:
    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int N = 1e6 + 9;
    const ll mod = 1e9 + 7;
    vector<ll> G[N];
    vector<ll> cnt_edge;
    vector<ll> tem;
    ll cnt[N];
    ll n;
    void dfs(int u, int fa) {
        bool f = 0;
        for (auto v : G[u]) {
            if (v == fa) continue;
            dfs(v, u);
            
            cnt[u] += cnt[v];
        }
        if (fa != -1)
        cnt_edge.push_back(cnt[u] * (n * 1ll - cnt[u]));
    }
    void solve() {
        scanf("%lld", &n);
        cnt[n] = 1;
        for (int i = 1; i < n; i++) {
            ll u, v;
            scanf("%lld%lld", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
            cnt[i] = 1;
        }
        dfs(1, -1);
        sort(cnt_edge.begin(), cnt_edge.end());
        reverse(cnt_edge.begin(), cnt_edge.end());
        ll m;
        scanf("%lld", &m);
        ll ans = 0;
        for (ll i = 1; i <= m; i++) {
            ll x;
            scanf("%lld", &x);
            tem.push_back(x);
        }
        sort(tem.begin(), tem.end());
        for (int i = 0; i < tem.size(); i ++) {
            tem[i] %= mod;
        }
        while (tem.size() > cnt_edge.size()) {
            ll x = tem[tem.size()-1];
            (x *= tem[tem.size() - 2]) %= mod;
            tem[tem.size() - 2] = x;
            tem.pop_back();
        }
        reverse(tem.begin(), tem.end());
        while (tem.size() < cnt_edge.size()) {
            tem.push_back(1);
        }
        for (ll i = 0; i < cnt_edge.size(); i++) {
            (ans += cnt_edge[i] * tem[i] % mod) %= mod;
        }
        printf("%lld
    ", ans);
        tem.clear();
        cnt_edge.clear();
        for (ll i = 1; i <= n; i++) G[i].clear();
    }
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.in", "r", stdin);
        freopen("out.out", "w", stdout);
    #endif
        ll n;
        scanf("%lld", &n);
        while (n--) {
            solve();
        }
        return 0;
    }
    
  • 相关阅读:
    元组类型
    字符串类型
    列表类型
    python 循环
    python语句
    python运算符
    python1
    软件管理
    rpm yum
    LVM
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/14832925.html
Copyright © 2011-2022 走看看