[CF1401D] Maximum Distributed Tree

[CF1401D] Maximum Distributed Tree

Description

给定一棵树,构造正整数边权,使得所有边权的乘积为 k,且边权为 1 的边数量最小,在此基础上,使得所有简单路径权值总和最大。

Solution

说白了就是分配一堆质因子,但是如果质因子个数比边数多,那么我们就把若干个最大的乘在一起

容易证明将质因子堆在一起比分散开来收益更多

每条边被走过的次数是确定的,现在就是边被经过次数和边权都确定了,我们只要确定二者之间的对应关系,贪心匹配即可

#include <bits/stdc++.h>
using namespace std;

#define int long long

void solve()
{
    int n;
    cin >> n;
    vector<vector<int>> g(n + 2);
    for (int i = 1; i < n; i++)
    {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    vector<int> siz(n + 2);
    function<void(int, int)> dfs = [&](int p, int from) {
        siz[p] = 1;
        for (int q : g[p])
            if (q != from)
                dfs(q, p), siz[p] += siz[q];
    };
    dfs(1, 0);
    vector<int> weight(n + 2);
    for (int i = 2; i <= n; i++)
        weight[i] = siz[i] * (n - siz[i]);
    sort(&weight[2], &weight[n + 1]);
    int m;
    cin >> m;
    const int mod = 1e9 + 7;
    vector<int> val(n + 2);
    vector<int> src(m + 2);
    for (int i = 1; i <= m; i++)
        cin >> src[i];
    sort(&src[1], &src[m + 1]);
    for (int i = 1; i <= n; i++)
        val[i] = 1;
    if (m > n - 1)
    {
        for (int i = n; i <= m; i++)
            src[n - 1] = src[n - 1] * src[i] % mod;
        for (int i = 2; i <= n; i++)
            val[i] = src[i - 1];
    }
    else
    {
        for (int i = n - m + 1; i <= n; i++)
            val[i] = src[i - n + m];
    }
    int ans = 0;
    for (int i = 2; i <= n; i++)
        ans = (ans + val[i] * weight[i]) % mod;
    cout << ans << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
        solve();
}
原文地址:https://www.cnblogs.com/mollnn/p/14399092.html