Codeforces Round #665 (Div. 2) D
D. Maximum Distributed Tree
显然对于一条路径 我们一个全的简单路径
显然就是左边子树*右边子树
我们先将每一条边的次数算出来
然后分类讨论:
要是m>n-1
我们显然要将后面的合并起来 全交给一个次数最多的边 显然最优
要是对于m<n-1
我们因为要满足那三个原则 我们直接对应起来即可
警惕先模再排序!!!
警惕先模再排序!!!
警惕先模再排序!!!
警惕先模再排序!!!
警惕先模再排序!!!
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int M = 998244353;
const int mod = 1e9+7;
#define int long long
int up(int a,int b){return a<0?a/b:(a+b-1)/b;}
#define endl '\n'
#define all(x) (x).begin(),(x).end()
#define YES cout<<"YES"<<endl;
#define NO cout<<"NO"<<endl;
#define _ 0
#define pi acos(-1)
#define INF 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
vector<int>g[N];
vector<int>seg;
int n,m;
int dfs(int u,int fa){
int res=1;
for(auto v:g[u]){
if(v==fa)continue;
res+=dfs(v,u);
}
if(fa)seg.push_back(res*(n-res));
return res;
}
void solve() {
cin>>n;seg.clear();
vector<int>p;
for(int i=1;i<=n;i++)g[i].clear();
for(int i=1;i<n;i++){
int u,v;cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
cin>>m;
for(int i=1;i<=m;i++){
int x;cin>>x;
p.push_back(x);
}
sort(all(p));
while(p.size()>n-1){
int a=p.back();
p.pop_back();
int b=p.back();
p.pop_back();
p.push_back(b*a%mod);
}
dfs(1,0);
sort(all(seg),greater<>());
std::reverse(p.begin(), p.end());
while(p.size()!=n-1)p.push_back(1);
int ans=0;
for(int i=n-2;i>=0;i--)(ans+=seg[i]%mod*p[i]%mod)%=mod;
cout<<ans<<endl;
}
signed main(){
fast
int t;t=1;cin>>t;
while(t--) {
solve();
}
return ~~(0^_^0);
}