D. Maximum Distributed Tree

题意

给你n个点n-1条边的树,再给你m个素数 p i p_i pi其乘积为k,k很大。

让你给每条边赋权,且 n − 1 n-1 n1条边权乘积为k

let ∑ i = 1 n − 1 ∑ j = i + 1 n f ( i , j ) \sum_{i=1}^{n-1}\sum_{j=i+1}^{n} f(i,j) i=1n1j=i+1nf(i,j)

思路

建图后跑dfs求出sz数组,然后考虑每条边被经过的次数 s z [ i ] ∗ ( n − s z [ i ] ) sz[i]*(n-sz[i]) sz[i](nsz[i])(为什么是这个公式,是因为他是一个全经过且不重边的图)

然后考虑m和n的大小,如果m过大就把p[n-1]增大,然后求和

#include<bits/stdc++.h>

using namespace std;
const int mod=1e9+7;
const int maxn=2e5+10;
typedef long long ll;
#define int long long

int p[maxn],sz[maxn];

vector<int>edge[maxn];

void dfs(int u,int fa){
    sz[u]=1;
    for(auto v:edge[u]){
        if(v==fa)continue;
        dfs(v,u);
        sz[u]+=sz[v];

    }

}

void solve(){
    int n;cin>>n;
    for(int i=1;i<maxn;++i){
        sz[i]=0;
        edge[i].clear();
        p[i]=1;
    }

    for(int _=1;_<n;++_){
        int u,v;cin>>u>>v;
        edge[u].push_back(v);
        edge[v].push_back(u);
    }

    int m;cin>>m;
    for(int i=1;i<=m;++i){
        cin>>p[i];
    }
    if(m<n-1)m=n-1;
    sort(p+1,p+1+m);
    for(int i=n;i<=m;++i){
        p[n-1]*=p[i];
        p[n-1]%=mod;
    }
    dfs(1,0);
    vector<int>val;
    for(int i=2;i<=n;++i){
        val.push_back(sz[i]*(n-sz[i]));
    }

    sort(val.begin(),val.end());

    int ans=0;
    for(int i=1;i<n;++i){
        ans=(ans+(val[i-1]%mod*p[i]%mod)%mod)%mod;
    }

    cout<<ans<<endl;

}

signed main(){
    int t;cin>>t;
    while(t--){
        solve();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值