​传送门​

题目大意

给定一棵 Codeforces 1401 D_测试数据个节点,Codeforces 1401 D_数据_02 条边的树。你可以在每一条树上的边标上边权,使得:
每个边权都为 正整数;
Codeforces 1401 D_数据_02个边权的乘积等于Codeforces 1401 D_i++_04
边权为 Codeforces 1401 D_数据_05 的边的数量最少。
定义 Codeforces 1401 D_数据_06 表示节点Codeforces 1401 D_测试数据_07到节点 Codeforces 1401 D_数据_08的简单路径经过的边权总和。你的任务是让Codeforces 1401 D_数据_09最大。
最终答案可能很大,对Codeforces 1401 D_数据_10取模即可。
Codeforces 1401 D_i++_04有可能很大,输入数据中包含了Codeforces 1401 D_测试数据_12个质数Codeforces 1401 D_i++_13 ,那么Codeforces 1401 D_i++_04为这些质数的乘积。
输入格式
第一行,一个整数Codeforces 1401 D_测试数据_15,表示多组测试数据个数。对于每一个测试数据:
第一行,一个整数 Codeforces 1401 D_测试数据_16,表示树上节点数;
Codeforces 1401 D_数据_17Codeforces 1401 D_测试数据行,每行两个整数Codeforces 1401 D_i++_19Codeforces 1401 D_数据_20,描述了一条无向边;
Codeforces 1401 D_数据_21行,一个整数Codeforces 1401 D_i++_22,表示Codeforces 1401 D_i++_04分解成质因子的个数;
Codeforces 1401 D_测试数据_24行,Codeforces 1401 D_测试数据_12个质数Codeforces 1401 D_数据_26
数据保证所有的Codeforces 1401 D_测试数据总和不超过Codeforces 1401 D_i++_28,所有的Codeforces 1401 D_测试数据_12总和不超过Codeforces 1401 D_测试数据_30
数据给出的边保证能够形成一棵树。

思路

考虑每条边对答案有多少次贡献。一条路径被经过,仅当起点是它左边的一个点,终点是它右边的一个点。贡献=左边点个数Codeforces 1401 D_i++_31右边点个数Codeforces 1401 D_i++_31边权。然后把最大的边权分给出现次数最多的就可以了。
Codeforces 1401 D_i++_33时,要填上Codeforces 1401 D_数据_05直到Codeforces 1401 D_测试数据_35
Codeforces 1401 D_i++_36时,要把多余的最大的合并成一个新的数,值为数的积,直到Codeforces 1401 D_测试数据_35

代码

ll t,n,m,ans;
ll p[maxn],s[maxn];
vector<ll> e[maxn];
priority_queue<ll> q;

void init(){
memset(s,0,sizeof s);
memset(p,0,sizeof p);
ans=0;
for(int i=1;i<=n;i++){
e[i].clear();
}
while(!q.empty()) q.pop();
}

void dfs(ll x,ll f){
s[x]=1;
for(int i=0;i<e[x].size();i++){
ll y=e[x][i];
if(y==f) continue;
dfs(y,x);
s[x]+=s[y];
}
}

void dfs2(ll x,ll f){
for(int i=0;i<e[x].size();i++){
ll y=e[x][i];
if(y==f) continue;
q.push(s[y]*(n-s[y]));
dfs2(y,x);
}
}

int cmp(ll a,ll b){
return a>b;
}

int main(){
int t;
cin>>t;
while(t--){
init();
scanf("%lld",&n);ll x,y;
for(int i=1;i<=n-1;i++){
scanf("%lld%lld",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
scanf("%lld",&m);
for(int i=1;i<=m;i++){
scanf("%lld",&p[i]);//质数
}
dfs(1,0);
dfs2(1,0);
sort(p+1,p+1+m,cmp);
if(m<=(n-1)){
ll top=1;
while(!q.empty()){
if(top<=m) ans+=q.top()*p[top];
else ans+=q.top();
ans%=mod;
q.pop();
top++;
}
}
else{
ll top=m-n+2;
ll sum=1;
for(int i=1;i<=(m-(n-1))+1;i++)
{
(sum*=p[i])%=mod;
}
p[top]=sum;

while(q.size())
{
(ans+=q.top()*p[top])%=mod;
q.pop();
top++;
}
}
printf("%lld\n",ans);
}
}