题目描述
You are given a tree that consists of n nodes. You should label each of its n−1 edges with an integer in such way that satisfies the following conditions:
each integer must be greater than 0;
the product of all n−1 numbers should be equal to k;
the number of 1-s among all n−1 integers must be minimum possible.
Let’s define f(u,v) as the sum of the numbers on the simple path from node u to node v. Also, let ∑i=1n−1∑j=i+1nf(i,j) be a distribution index of the tree.
Find the maximum possible distribution index you can get. Since answer can be too large, print it modulo 109+7.
In this problem, since the number k can be large, the result of the prime factorization of k is given instead.
Input
The first line contains one integer t (1≤t≤100) — the number of test cases.
The first line of each test case contains a single integer n (2≤n≤105) — the number of nodes in the tree.
Each of the next n−1 lines describes an edge: the i-th line contains two integers ui and vi (1≤ui,vi≤n; ui≠vi) — indices of vertices connected by the i-th edge.
Next line contains a single integer m (1≤m≤6⋅104) — the number of prime factors of k.
Next line contains m prime numbers p1,p2,…,pm (2≤pi<6⋅104) such that k=p1⋅p2⋅…⋅pm.
It is guaranteed that the sum of n over all test cases doesn’t exceed 105, the sum of m over all test cases doesn’t exceed 6⋅104, and the given edges for each test cases form a tree.
Output
Print the maximum distribution index you can get. Since answer can be too large, print it modulo 109+7.
Example
input
3
4
1 2
2 3
3 4
2
2 2
4
3 4
1 3
3 2
2
3 2
7
6 1
2 3
4 6
7 3
5 1
3 6
4
7 5 13 3
output
17
18
286
Note
In the first test case, one of the optimal ways is on the following image:
In this case, f(1,2)=1, f(1,3)=3, f(1,4)=5, f(2,3)=2, f(2,4)=4, f(3,4)=2, so the sum of these 6 numbers is 17.
In the second test case, one of the optimal ways is on the following image:
In this case, f(1,2)=3, f(1,3)=1, f(1,4)=4, f(2,3)=2, f(2,4)=5, f(3,4)=3, so the sum of these 6 numbers is 18.
题目大意
给你一棵树,你可以在树的边上标权值,使得:
1.每个边权都为正整数
2.这n-1个边权的 乘积 等于 k
3.边权为1的边的数量最少。
f(u,v)为节点u到v的简单路径的权值和。求所有f(u,v)的和的最大值。
题目分析
这道题的难点在于:如何求出每一条边被经过的次数。
我们可以定义sz[i]为以i为根的子树的大小,那么i->fa(i)这条边被经过的次数a[i] 即为:a[i]=sz[i]*(n-sz[i])
只要找出来每一条边被经过的次数,后面只需要简单的贪心即可。
如果所给权值m小于边数cnt,那么就将权值p[i]从大到小给从大到小的a[i],剩下的a[i]的所给权值即为1。
如果所给权值m大于边数cnt,那么就将最大的m-cnt个权值相乘变为一个权值,再将这cnt个权值p[i]从大到小分配给从大到小的a[i]。
代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <iomanip>
#define LL long long
#define PII pair<int,int>
using namespace std;
const int N=1e5+5,mod=1e9+7;
vector<LL> g[N]; //存图
int n,m,cnt;
LL p[N],a[N],sz[N]; //p[]所给权值,a[]存所有边被经过的次数,sz[i]以i为根的子树的大小
void init() //初始化
{
cnt=0;
for(int i=0;i<=n;i++)
g[i].clear();
}
void dfs(int u,int fa) //dfs求出a[]
{
sz[u]=1; //初始大小为1
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v==fa) continue;
dfs(v,u); //递归
sz[u]+=sz[v]; //更新u子树的大小
a[++cnt]=sz[v]*(n-sz[v]); //将结果存到a[]中
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
init();
for(int i=1;i<n;i++) //建图
{
int u,v;
scanf("%d %d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%d",&p[i]);
dfs(1,0); //dfs求a[]
LL ans=0;
if(m<n-1) //m小于边数的情况
{
sort(a+1,a+cnt+1,greater<LL>());
sort(p+1,p+m+1,greater<int>());
for(int i=1;i<=m;i++)
ans=(ans+p[i]*a[i]%mod)%mod;
for(int i=m+1;i<=cnt;i++)
ans=(ans+a[i])%mod;
}
else //m大于边数的情况
{
sort(a+1,a+1+cnt);
sort(p+1,p+1+m);
LL k=1;
for(int i=cnt+1;i<=m;i++)
k=(k*p[i])%mod;
p[cnt]=(p[cnt]*k)%mod;
for(int i=1;i<=cnt;i++)
ans=(ans+a[i]*p[i]%mod)%mod;
}
printf("%d\n",ans); //输出ans
}
return 0;
}