题目
[CodeForces 1401D] Maximum Distributed Tree
分析
边 ( u , v ) (u, v) (u,v) ( v v v 的深度大于 u u u)被统计的次数是 s i z v ( n − s i z v ) siz_v(n - siz_v) sizv(n−sizv),因此我们目的变成给 n − 1 n - 1 n−1 个数分配 m m m 个权使得每个数与其分配到的所有权之积的和最大。显然是大数对大权,因此排序即可。
代码
#include <bits/stdc++.h>
int Read() {
int x = 0; char c = getchar();
while (c < '0' || c > '9')
c = getchar();
while (c >= '0' && c <= '9')
x = x * 10 + (c ^ 48), c = getchar();
return x;
}
typedef long long LL;
const int MAXN = 100000;
const int MAXM = 60000;
const int MOD = 1000000007;
int N, M, Siz[MAXN + 5];
std::vector<int> G[MAXN + 5];
int Cnt;
LL Num[MAXN + 5];
int Pri[MAXM + 5];
void Dfs(int u, int f) {
Siz[u] = 1;
for (int v: G[u])
if (v != f)
Dfs(v, u), Siz[u] += Siz[v];
if (u != 1)
Num[++Cnt] = (LL)Siz[u] * (N - Siz[u]);
}
int main() {
int T = Read();
while (T--) {
Cnt = 0;
N = Read();
for (int i = 1; i <= N; i++)
G[i].clear();
for (int i = 1; i < N; i++) {
int u = Read(), v = Read();
G[u].push_back(v), G[v].push_back(u);
}
M = Read();
for (int i = 1; i <= M; i++)
Pri[i] = Read();
Dfs(1, 0);
std::sort(Num + 1, Num + Cnt + 1);
std::sort(Pri + 1, Pri + M + 1);
int Ans = 0;
if (Cnt >= M) {
for (int i = M; i >= 1; i--)
Ans = (Ans + Num[i + Cnt - M] * Pri[i] % MOD) % MOD;
for (int i = 1; i <= Cnt - M; i++)
Ans = (Ans + Num[i]) % MOD;
}
else {
for (int i = M; i > Cnt; i--)
Num[Cnt] = Num[Cnt] * Pri[i] % MOD;
for (int i = Cnt; i >= 1; i--)
Ans = (Ans + Num[i] * Pri[i] % MOD) % MOD;
}
printf("%d\n", Ans);
}
return 0;
}