欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

BZOJ3872 : [Poi2014]Ant colony

程序员文章站 2022-07-13 12:41:33
...

设i点的度数为d[i]

则如果有x只蚂蚁在从i走到别处,会分裂成每群$\lfloor\frac{x}{d[i]-1}\rfloor$只蚂蚁

对于x出发的m只蚂蚁,到y处还剩$\lfloor\frac{m}{x到y路径上所有点度数-1的乘积}\rfloor$

于是我们一遍DFS求出到每个叶子节点时一路上点度数-1的乘积,再在数组中二分查找出一个合法的区间即可

 

#include<cstdio>
#include<algorithm>
#define N 1000010
typedef long long ll;
int n,m,k,i,j,x,y,g[N],nxt[N<<1],v[N<<1],d[N],ed,a[N];ll ans;
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void add(int x,int y){d[x]++;v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
inline int ask(ll x){
  if(x>a[m])return m;
  if(x<=a[1])return 0;
  int l=1,r=m,t,mid;
  while(l<=r)if(a[mid=(l+r)>>1]<x)l=(t=mid)+1;else r=mid-1;
  return t;
}
void dfs(int x,int y,int t){
  if(!d[x])ans+=ask((ll)(k+1)*t)-ask((ll)k*t);
  if((ll)t*d[x]>a[m])return;t*=d[x];
  for(int i=g[x];i;i=nxt[i])if(i>2&&v[i]!=y)dfs(v[i],x,t);
}
int main(){
  read(n),read(m),read(k);
  for(i=1;i<=m;i++)read(a[i]);
  std::sort(a+1,a+m+1);
  for(i=1;i<n;i++)read(x),read(y),add(x,y),add(y,x);
  for(i=1;i<=n;i++)d[i]--;
  dfs(v[1],0,1);dfs(v[2],0,1);
  return printf("%lld",ans*k),0;
}