【BZOJ3872】[Poi2014]Ant colony 樹形DP+二分
阿新 • • 發佈:2017-10-29
pro 數組 通過 main ram ret dot getc style
一只饑餓的食蟻獸埋伏在一條邊上,如果有一群螞蟻通過這條邊,並且數量恰為k只,它就會吞掉這群螞蟻。請計算一共有多少只螞蟻會被吞掉。
7 5 3
3 4 1 9 11
1 2
1 4
4 3
4 5
4 6
6 7
【BZOJ3872】[Poi2014]Ant colony
Description
給定一棵有n個節點的樹。在每個葉子節點,有g群螞蟻要從外面進來,其中第i群有m[i]只螞蟻。這些螞蟻會相繼進入樹中,而且要保證每一時刻每個節點最多只有一群螞蟻。這些螞蟻會按以下方式前進: ·在即將離開某個度數為d+1的點時,該群螞蟻有d個方向還沒有走過,這群螞蟻就會分裂成d群,每群數量都相等。如果d=0,那麽螞蟻會離開這棵樹。 ·如果螞蟻不能等分,那麽螞蟻之間會互相吞噬,直到可以等分為止,即一群螞蟻有m只,要分成d組,每組將會有floor(m/d)只,如下圖。Input
第一行包含三個整數n,g,k,表示點數、螞蟻群數以及k。 第二行包含g個整數m[1],m[2],...,m[g],表示每群螞蟻中螞蟻的數量。 接下來n-1行每行兩個整數,表示一條邊,食蟻獸埋伏在輸入的第一條邊上。Output
Your program should print to the standard output a single line containing a single integer: the number of ants eaten by the anteater. 一個整數,即食蟻獸能吃掉的螞蟻的數量。Sample Input
3 4 1 9 11
1 2
1 4
4 3
4 5
4 6
6 7
Sample Output
21題解:可以先把第一條邊拆掉,然後分成兩棵樹進行樹形DP。因為根節點的取值是確定的,並且每個點的度數也是確定的,所以可以根據父親的取值範圍得出兒子的取值範圍,最終得出所有葉子節點的取值範圍。然後將m數組排序,對於每個節點都在m數組裏二分一下統計答案即可。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int maxn=1000010; const ll inf=1<<30; int n,m,cnt,r1,r2; ll K,ans; int to[maxn<<1],next[maxn<<1],head[maxn],d[maxn],fa[maxn]; ll l[maxn],r[maxn],v[maxn]; inline void add(int a,int b) { to[cnt]=b,next[cnt]=head[a],head[a]=cnt++; } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } void dfs(int x) { for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[x]) { fa[to[i]]=x; if(d[to[i]]==1) l[to[i]]=l[x],r[to[i]]=r[x]; else l[to[i]]=min(inf,l[x]*(d[to[i]]-1)),r[to[i]]=min(inf,(r[x]+1)*(d[to[i]]-1)-1); dfs(to[i]); } } int main() { n=rd(),m=rd(),K=rd(); int i,a,b; for(i=1;i<=m;i++) v[i]=rd(); v[m+1]=inf+1; sort(v+1,v+m+1); r1=rd(),r2=rd(),d[r1]++,d[r2]++; memset(head,-1,sizeof(head)); for(i=1;i<n-1;i++) a=rd(),b=rd(),add(a,b),add(b,a),d[a]++,d[b]++; if(d[r1]==1) l[r1]=r[r1]=K; else l[r1]=K*(d[r1]-1),r[r1]=(K+1)*(d[r1]-1)-1; if(d[r2]==1) l[r2]=r[r2]=K; else l[r2]=K*(d[r2]-1),r[r2]=(K+1)*(d[r2]-1)-1; dfs(r1),dfs(r2); for(i=1;i<=n;i++) if(d[i]==1) a=lower_bound(v+1,v+m+1,l[i])-v,b=upper_bound(v+1,v+m+1,r[i])-v,ans+=(b-a)*K; printf("%lld",ans); return 0; }
【BZOJ3872】[Poi2014]Ant colony 樹形DP+二分