D. Maximum Distributed Tree(DFS)
思路: d f s dfs dfs讨论一下 m m m与 n − 1 n-1 n−1的大小关系,然后计算每条边的贡献次数排序即可。
没想到最后因为数组开小了一直没 A C AC AC,气死了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,M=6e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define il inline
int n,sz[N],p[N];
vector<int>e[N];
vector<ll>f;
void dfs(int u,int fa){
sz[u]=1;
for(int v:e[u]){
if(v==fa) continue;
dfs(v,u);
sz[u]+=sz[v];
}
ll x=1LL*sz[u]*(n-sz[u]);
f.pb(x);
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++) e[i].clear(),sz[i]=p[i]=0;//之前就是因为p[]开的太小,越界了。
f.clear();
for(int i=1;i<n;i++){
int u,v;scanf("%d%d",&u,&v);
e[u].pb(v),e[v].pb(u);
}
int m;
scanf("%d",&m);
deque<ll>q;
for(int i=1;i<=m;i++){
scanf("%d",&p[i]);
}
sort(p+1,p+m+1,greater<int>());
int id=1;
int op=0,m1=m;
if(m>n-1){
op=1;
ll x=1;
while(m>=n-1){
x=x*p[id++]%mod;
m--;
}
q.push_back(x);
for(int i=id;i<=m1;i++)
q.push_back(1LL*p[i]);
}
dfs(1,0);
sort(f.rbegin(),f.rend());
ll ans=0;
if(op){
for(int i=1;i<n;i++){
//printf("f=%lld,q=%lld\n",f[i-1],q.front());
ans=(ans+1LL*f[i-1]%mod*q.front()%mod)%mod;
q.pop_front();
}
}
else {
for(int i=1;i<n;i++){
if(!p[i]) p[i]=1;
ans=(ans+1LL*f[i-1]%mod*p[i]%mod)%mod;
}
}
printf("%lld\n",ans);
}
return 0;
}