# Codeforces Round #665 (Div. 2) D. Maximum Distributed Tree

m的质因数分解形式也从大到小排序，要求1最少，那就优先给每个w排上一个数，由排序不等式（或者直觉），大的配大的

#include<bits/stdc++.h>

using namespace std;

inline int rd(){
int ret=0,f=1;char c;
while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
while(isdigit(c))ret=ret*10+c-'0',c=getchar();
return ret*f;
}
#define pc putchar
#define space() pc(' ')
#define nextline() pc('\n')
void pot(int x){if(!x)return;pot(x/10);pc('0'+x%10);}
void out(int x){if(!x)pc('0');if(x<0)pc('-'),x=-x;pot(x);}

const int MOD = 1e9+7;
const int MAXN = 100005;

struct Edge{
int next,to;
}e[MAXN<<1];
int head[MAXN],ecnt;
inline void add(int x,int y){
e[++ecnt].next = head[x];
e[ecnt].to = y;
head[x] = ecnt;
}

typedef long long ll;

int n,m;
ll ps[MAXN],w[MAXN];

int siz[MAXN];
void dfs(int x,int pre){
siz[x]=1;
for(int i=head[x];i;i=e[i].next){
int v=e[i].to;
if(v==pre) continue;
dfs(v,x);
siz[x]+=siz[v];
}
}

void solve(){
memset(siz,0,sizeof(siz));
memset(head,0,sizeof(head));
memset(ps,0,sizeof(ps));
ecnt=0;
//clear
n=rd();
int x,y;
for(int i=1;i<=n-1;i++){
x=rd();y=rd();
add(x,y);add(y,x);
}
m=rd();
for(int i=1;i<=m;i++){
ps[i]=rd();
}
sort(ps+1,ps+1+m);
reverse(ps+1,ps+1+m);
dfs(1,-1);
for(int i=1;i<=ecnt;i+=2){
int u=e[i].to;
int v=e[i+1].to;
ll mn=min(siz[u],siz[v]);
w[(i+1)>>1]=1ll*mn*(n-mn);

//		w[(i+1)>>1]=mn;
}
sort(w+1,w+1+(n-1));
reverse(w+1,w+1+(n-1));
//	cerr<<"DEBUG:";
//	for(int i=1;i<=n-1;i++) cerr<<w[i]<<" ";
//	cerr<<endl;
ll ans=0;
if((n-1)>=m){
for(int i=1;i<=n-1;i++){
int y=ps[i];
if(y==0) y=1;
ans+=(ll)(1ll*w[i]*y);
ans%=MOD;
}
//		cerr<<"ANS:";
cout<<ans<<endl;
return;
}else{
ll tmp=1;
for(int i=1;i<=(m-n+2);i++){
tmp*=(ll)(1ll*ps[i]);
tmp%=MOD;
}
ans+=(ll)(1ll*tmp*w[1]);
ans%=MOD;
for(int i=2;i<=n-1;i++){
int j=i+m-n+1;
ans+=(ll)(1ll*w[i]*ps[j]);
ans%=MOD;
}
//		cerr<<"ANS:";
cout<<ans<<endl;
return;
}

}

int main(){
int t=rd();
while(t--) solve();
return 0;
}


posted @ 2020-08-23 15:48  GhostCai  阅读(83)  评论(0编辑  收藏  举报