BZOJ3872 : [Poi2014]Ant colony

设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;
}

  

 

posted @ 2015-01-17 16:46  Claris  阅读(360)  评论(0编辑  收藏  举报