[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();
}