[POI2014]Ant colony
题目大意:
给定一棵$n(n\le10^6)$个结点的树。在每个叶子结点,有$g$群蚂蚁要从外面进来,其中第$i$群有$m_i$只蚂蚁。这些蚂蚁依次爬树(一群蚂蚁爬完后才会爬另一群),若当前经过结点度为$d+1$,蚂蚁数量为$m$,则接下来没走过的$d$个方向,每个方向爬$\lfloor\frac md\rfloor$只蚂蚁,剩下蚂蚁消失。在给定的一条边上有一只食蚁兽,若当前经过这条边的蚂蚁数量为$k$,则吃掉这些蚂蚁。问最后能吃到多少蚂蚁?
思路:
从给定边出发BFS,算出每条边会被吃掉的蚁群规模的上界和下界。若到了叶子节点,就在$\{m_i\}$中二分。然后洛谷和SZKOpuł上都能随便AC,BZOJ大力卡一波常才过。
1 #include<cstdio> 2 #include<algorithm> 3 #include<sys/mman.h> 4 #include<sys/stat.h> 5 typedef long long int64; 6 class BufferedInputStream { 7 private: 8 char *buf,*p; 9 int size; 10 public: 11 BufferedInputStream() { 12 register int fd=fileno(stdin); 13 struct stat sb; 14 fstat(fd,&sb); 15 size=sb.st_size; 16 p=buf=reinterpret_cast<char*>(mmap(0,size,PROT_READ,MAP_PRIVATE,fileno(stdin),0)); 17 } 18 char getchar() { 19 return (p==buf+size||*p==EOF)?EOF:*p++; 20 } 21 }; 22 BufferedInputStream in; 23 inline int getint() { 24 register char ch; 25 while(!__builtin_isdigit(ch=in.getchar())); 26 register int x=ch^'0'; 27 while(__builtin_isdigit(ch=in.getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 28 return x; 29 } 30 const int N=1e6+1; 31 bool vis[N]; 32 int deg[N],q[N],head,tail,h[N],sz; 33 int64 m[N],max[N],min[N]; 34 struct Edge { 35 int to,next; 36 }; 37 Edge e[N<<1]; 38 inline void add_edge(const int &u,const int &v) { 39 e[++sz]=(Edge){v,h[u]};h[u]=sz;deg[u]++; 40 e[++sz]=(Edge){u,h[v]};h[v]=sz;deg[v]++; 41 } 42 int main() { 43 const int n=getint(),g=getint(),k=getint(); 44 int64 lim=0; 45 for(register int i=1;i<=g;i++) { 46 lim=std::max(lim,m[i]=getint()); 47 } 48 std::sort(&m[1],&m[g]+1); 49 for(register int i=1;i<n;i++) { 50 const int u=getint(),v=getint(); 51 if(i==1) { 52 max[u]=min[u]=max[v]=min[v]=k; 53 vis[u]=vis[v]=true; 54 q[tail++]=u; 55 q[tail++]=v; 56 } 57 add_edge(u,v); 58 } 59 int64 ans=0; 60 while(head<tail) { 61 const int &x=q[head++]; 62 if(deg[x]==1) { 63 ans+=(int64)(std::upper_bound(&m[1],&m[g]+1,max[x])-std::lower_bound(&m[1],&m[g]+1,min[x]))*k; 64 } 65 for(register int i=h[x];i;i=e[i].next) { 66 const int &y=e[i].to; 67 if(vis[y]) continue; 68 max[y]=std::min((max[x]+1)*(deg[x]-1)-1,lim); 69 min[y]=min[x]*(deg[x]-1); 70 vis[y]=true; 71 if(min[y]<=lim) q[tail++]=y; 72 } 73 } 74 __builtin_printf("%lld\n",ans); 75 return 0; 76 }