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);
}
posted @ 2022-10-28 21:42  ycllz  阅读(20)  评论(0)    收藏  举报