Maximum Distributed Tree CodeForces - 1401D
原题链接
考察:贪心+思维
思路:
说是D题,思路比C题明显,很明显经过次数最多的边赋最大的值,虽然是构造但思路非常明显.
难点是怎么计算经过每条边的次数(本蒟蒻就卡这了菜是原罪),经过查看题解观察可得对于一条边(u,v),有sz[v](v点以及v的子节点)个点会经过v到达u或者u以上的点,两两配对的方案数是sz[v]*(n-sz[v]).因为每个点标号一定不同,所以一定存在一个>一个<.
说一下我WA了8次的坑点,计算经过次数不能%,否则排序后计算的式子就与原来不一样.
Code
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 200010,M = 60010,Mod=1e9+7;
struct Road{
int to,ne;
}road[N<<1];
int idx,n,prime[M],m,sz[N],h[N],cnt;
LL sum[N<<1];
void add(int a,int b)
{
road[idx].to = b,road[idx].ne = h[a],h[a] = idx++;
}
void init()
{
cnt = idx = 0;
memset(sz,0,sizeof sz);
memset(h,-1,sizeof h);
}
int dfs(int u,int fa)
{
sz[u] = 1;
for(int i=h[u];~i;i=road[i].ne)
{
int v = road[i].to;
if(v==fa) continue;
sz[u]+=dfs(v,u);
sum[++cnt] = (LL)sz[v]*(n-sz[v]);
}//WA n次:sum不能%Mod
return sz[u];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init();
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b); add(b,a);
}
scanf("%d",&m);
prime[0] =1;
for(int i=1;i<=m;i++) scanf("%d",&prime[i]);
sort(prime+1,prime+m+1);
dfs(1,-1);
sort(sum+1,sum+cnt+1);
int res = 0;
if(cnt<m)
{
for(int i=m;i>cnt;i--)
prime[cnt] = (LL)prime[cnt]*prime[i]%Mod;
m = cnt;
}
for(int i=cnt,j=m;i>=1;i--,j--)
{
if(j<0) j = 0;
res+=(LL)sum[i]*prime[j]%Mod;
res%=Mod;
}
printf("%d\n",res);
}
return 0;
}