BZOJ_3872_[Poi2014]Ant colony_dfs

Description

There is an entrance to the ant hill in every chamber with only one corridor leading into (or out of) it. At each entry, there are g groups of m1,m2,...,mg ants respectively. These groups will enter the ant hill one after another, each successive group entering once there are no ants inside. Inside the hill, the ants explore it in the following way:
Upon entering a chamber with d outgoing corridors yet unexplored by the group, the group divides into d groups of equal size. Each newly created group follows one of the d corridors. If d=0, then the group exits the ant hill.
If the ants cannot divide into equal groups, then the stronger ants eat the weaker until a perfect division is possible. Note that such a division is always possible since eventually the number of ants drops down to zero. Nothing can stop the ants from allowing divisibility - in particular, an ant can eat itself, and the last one remaining will do so if the group is smaller than d.
The following figure depicts m ants upon entering a chamber with three outgoing unexplored corridors, dividing themselves into three (equal) groups of floor(m/3) ants each.
A hungry anteater dug into one of the corridors and can now eat all the ants passing through it. However, just like the ants, the anteater is very picky when it comes to numbers. It will devour a passing group if and only if it consists of exactly k ants. We want to know how many ants the anteater will eat.
给定一棵有n个节点的树。在每个叶子节点,有g群蚂蚁要从外面进来,其中第i群有m[i]只蚂蚁。这些蚂蚁会相继进入树中,而且要保证每一时刻每个节点最多只有一群蚂蚁。这些蚂蚁会按以下方式前进:
·在即将离开某个度数为d+1的点时,该群蚂蚁有d个方向还没有走过,这群蚂蚁就会分裂成d群,每群数量都相等。如果d=0,那么蚂蚁会离开这棵树。
·如果蚂蚁不能等分,那么蚂蚁之间会互相吞噬,直到可以等分为止,即一群蚂蚁有m只,要分成d组,每组将会有floor(m/d)只,如下图。
一只饥饿的食蚁兽埋伏在一条边上,如果有一群蚂蚁通过这条边,并且数量恰为k只,它就会吞掉这群蚂蚁。请计算一共有多少只蚂蚁会被吞掉。

Input

The first line of the standard input contains three integers n, g, k (2<=n,g<=1000000, 1<=k<=10^9), separated by single spaces. These specify the number of chambers, the number of ant groups and the number of ants the anteater devours at once. The chambers are numbered from 1 to n.
The second line contains g integers m[1],m[2],...,m[g](1<=m[i]<=10^9), separated by single spaces, where m[i] gives the number of ants in the i-th group at every entrance to the ant hill. The n-1 lines that follow describe the corridors within the ant hill; the i-th such line contains two integers a[i],b[i] (1<=a[i],b[i]<=n), separated by a single space, that indicate that the chambers no.a[i] and b[i] are linked by a corridor. The anteater has dug into the corridor that appears first on 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

7 5 3
3 4 1 9 11
1 2
1 4
4 3
4 5
4 6
6 7

Sample Output

21

 倒过来做,以最后输入的两端为根dfs整棵树。
求出每个点的蚂蚁数目范围,满足最后走到根时恰好剩下k个蚂蚁。
对于最大值upper[to[i]]=upper[x]*(out[x]-1)+out[x]-2.out[x]表示x的度数。
对于最小值lower[to[i]]=lower[x]*(out[x]-1)。
可能中间过程爆longlong,当最小值比总数大的时候就不必继续dfs下去。
然后对于每个初始的叶子结点二分查找一下合法蚂蚁的个数。
 
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
char nc() {
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd() {
register int x=0;
register char s=nc();
while(s<'0'||s>'9')s=nc();
while(s>='0'&&s<='9')x=(x<<3)+(x<<1)+s-'0',s=nc();
return x;
}
#define N 1000050
typedef long long ll;
int head[N],to[N<<1],nxt[N<<1],out[N],cnt;
int m[N],n,g,k,root1,root2;
ll upper[N],lower[N];
inline void add(int u,int v) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; out[u]++;
}
void dfs(int x,int y) {
int i;
for(i=head[x];i;i=nxt[i]) {
if(to[i]!=y) {
upper[to[i]]=upper[x]*(out[x]-1)+out[x]-2;
if(upper[to[i]]<0) upper[to[i]]=m[g];
upper[to[i]]=min(upper[to[i]],1ll*m[g]);
lower[to[i]]=lower[x]*(out[x]-1);
if(lower[to[i]]<=m[g]&&lower[to[i]]>=0)
dfs(to[i],x);
}
}
}
int search(ll x) {
int l=1,r=g+1;
while(l<r) {
int mid=(l+r)>>1;
if(m[mid]<=x) l=mid+1;
else r=mid;
}
return l-1;
}
int main() {
n=rd(); g=rd(); k=rd();
int i,x,y;
for(i=1;i<=g;i++) m[i]=rd();
sort(m+1,m+g+1);
root1=rd(); root2=rd();
add(root1,root2); add(root2,root1);
for(i=2;i<n;i++) {
x=rd(); y=rd();
add(x,y); add(y,x);
}
upper[root1]=upper[root2]=lower[root1]=lower[root2]=k;
dfs(root1,root2);
dfs(root2,root1);
ll ans=0;
for(i=1;i<=n;i++) if(out[i]==1) ans+=search(upper[i])-search(lower[i]-1);
printf("%lld\n",ans*k);
}

BZOJ_3872_[Poi2014]Ant colony_dfs的更多相关文章

  1. [BZOJ3872][Poi2014]Ant colony

    [BZOJ3872][Poi2014]Ant colony 试题描述 There is an entrance to the ant hill in every chamber with only o ...

  2. bzoj 3872: [Poi2014]Ant colony -- 树形dp+二分

    3872: [Poi2014]Ant colony Time Limit: 30 Sec  Memory Limit: 128 MB Description   There is an entranc ...

  3. 【BZOJ3872】[Poi2014]Ant colony 树形DP+二分

    [BZOJ3872][Poi2014]Ant colony Description 给定一棵有n个节点的树.在每个叶子节点,有g群蚂蚁要从外面进来,其中第i群有m[i]只蚂蚁.这些蚂蚁会相继进入树中, ...

  4. [bzoj3872][Poi2014]Ant colony_树形dp

    Ant colony bzoj-3872 Poi-2014 题目大意:说不明白.....题目链接 注释:略. 想法:两个思路都行. 反正我们就是要求出每个叶子节点到根节点的每个路径权值积. 可以将边做 ...

  5. [POI2014]Ant colony

    题目大意: 给定一棵$n(n\le10^6)$个结点的树.在每个叶子结点,有$g$群蚂蚁要从外面进来,其中第$i$群有$m_i$只蚂蚁.这些蚂蚁依次爬树(一群蚂蚁爬完后才会爬另一群),若当前经过结点度 ...

  6. bzoj 3872 [Poi2014]Ant colony——二分答案

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3872 可以倒推出每个叶子节点可以接受的值域.然后每个叶子二分有多少个区间符合即可. 注意一开 ...

  7. bzoj 3872: [Poi2014]Ant colony【树形dp+二分】

    啊我把分子分母混了WA了好几次-- 就是从食蚁兽在的边段成两棵树,然后dp下去可取的蚂蚁数量区间,也就是每次转移是l[e[i].to]=l[u](d[u]-1),r[e[i].to]=(r[u]+1) ...

  8. $bzoj3872\ [Poi2014]\ Ant\ colony$ 二分+$dp$

    正解:二分+$dp$ 解题报告: 传送门$QwQ$ 一年过去了依然没有头绪,,,$gql$的$NOIp$必将惨败了$kk$. 考虑倒推,因为知道知道除数和答案,所以可以推出被除数的范围,然后一路推到叶 ...

  9. POI2014题解

    POI2014题解 [BZOJ3521][Poi2014]Salad Bar 把p当作\(1\),把j当作\(-1\),然后做一遍前缀和. 一个合法区间\([l,r]\)要满足条件就需要满足所有前缀和 ...

随机推荐

  1. 2MySQL Server 系统架构

    2.2MySQL Server 系统架构 总的来说,MySQL 可以看成是二层架构,第一层我们通常叫做SQL Layer,在MySQL 数据库系统处理底层数据之前的所有工作都是在这一层完成的,包括权限 ...

  2. redis分布式锁实践

    分布式锁在多实例部署,分布式系统中经常会使用到,这是因为基于jvm的锁无法满足多实例中锁的需求,本篇将讲下redis如何通过Lua脚本实现分布式锁,不同于网上的redission,完全是手动实现的 我 ...

  3. AngularJs 学习笔记(三)依赖注入

    一个对象可以通过三种方式来获取对依赖对象的控制权: 1.在内部创建依赖的对象 2.通过全局变量引用这个依赖对象 3.通过参数进行传递(在这里是通过函数参数) AngularJs通过$injector注 ...

  4. golang升级

    系统安装软件一般在/usr/share,可执行的文件在/usr/bin,配置文件可能安装到了/etc下等. 文档一般在 /usr/share 可执行文件 /usr/bin 配置文件 /etc lib文 ...

  5. ubuntu11.04安装nginx+php+mysql

    先列参考内容,后面我再补充点东西: http://www.4wei.cn/archives/1001436 http://www.gidot.net/blog/article.asp?id=322 上 ...

  6. ffmpeg转换参数和压缩输出大小的比率 参考 最新版本FFMPEG

    https://blog.cnlabs.NET/3668.html ffmpeg 转换压缩比例 FFMPEG如果是压缩为FLV文件 3个编码可选1. -c:v flv 标准FLV编码 这个好处是速度快 ...

  7. Jmeter(二十六)_数据驱动测试

    花了一点时间做了一个通用的执行引擎,好处就是我不用再关注测试脚本的内容,而是用测试用例的数据去驱动我们执行的方向.(这个只适合单个接口的测试,具体运用到接口自动化时,还是要靠手动去编写脚本!) 首先我 ...

  8. unix中的rm,rmdir的使用

    一.rm的使用 1.基本用法:用于删除文件 rm filename 2.可加属性值 (1)-v rm -v filename 作用:提示删除的情况 (2)-f  rm -f filename 作用:删 ...

  9. Angular路由——路由守卫

    一.路由守卫 当用户满足一定条件才被允许进入或者离开一个路由. 路由守卫场景: 只有当用户登录并拥有某些权限的时候才能进入某些路由. 一个由多个表单组成的向导,例如注册流程,用户只有在当前路由的组件中 ...

  10. JS前端调用后台方法

    //JS前端代码function Exportqmdltb() { var areavalue= GetQmdltmValue(); $.ajax({ type: "post", ...