luogu P4183 Cow at Large P (暴力吊打点分治)(内有时间复杂度证明)
题面
贝茜被农民们逼进了一个偏僻的农场。农场可视为一棵有N个结点的树,结点分别编号为 1,2,…,N 。每个叶子结点都是出入口。开始时,每个出入口都可以放一个农民(也可以不放)。每个时刻,贝茜和农民都可以移动到相邻的一个结点。如果某一时刻农民与贝茜相遇了(在边上或点上均算),则贝茜将被抓住。抓捕过程中,农民们与贝茜均知道对方在哪个结点。
请问:对于结点 i\((1\leq i\leq N)\),如果开始时贝茜在该结点,最少有多少农民,她才会被抓住。
分析
先考虑问题的简化版,对于给定的起点s求出答案
设dist(x,y)表示x,y两点之间的距离
我们发现,对于某一个节点x,若$dist(s,x) \geq \min {dist(x,u) } $ 其中u为x的子树中的叶子节点,那么从x走到s的时
候就会被抓住.$\min {dist(x,u) } $可以通过一次BFS预处理出来
显然奶牛越早被抓住更好,从节点s出发DFS,只要当前节点x满足上述条件,则ans++,并不访问x子树中的节点。因为如果在x点被抓住了,它就不会到比x深度更大的节点去了
这样的复杂度显然是\(O(n^2)\)
有一个玄学优化,可以通过此题,方法如下
1.DP一遍求出每个点到最近的叶子节点的距离dp[x]
2.DFS,把链缩成一条边,因为可以发现不管在链的哪里拦截都是一样的
3.每次暴力,当dp[x]<=dist(x,root)的时候ans++,return
可以证明把链缩掉之后是\(O(n\sqrt{n})\)的
由于没有链,我们可以把模型简化为一个满k叉树(k>1),每次暴力DFS,显然DFS的深度不超过树的深度的1/2,即\(O(log_kn)\)
访问的子树大小为
\]
显然当k=2最大,为\(2\sqrt{n}-1\),
所以总时间复杂度为\(O(n\sqrt{n})\),与分块相同,且常数远小于点分治
代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define maxn 100005
#define INF 0x3f3f3f3f
using namespace std;
inline void qread(int &x){
x=0;
char c=getchar();
while(c<'0'||c>'9'){
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
}
inline void qprint(int x){
if(x==0){
putchar('0');
return;
}else{
if(x>=10) qprint(x/10);
putchar(x%10+'0');
}
}
int n,k;
struct edge{
int from;
int to;
int next;
int nfrom;
int nto;
int len;
}E[maxn<<1];
int head[maxn];
int deg[maxn];
int sz=1;
void add_edge(int u,int v){
deg[u]++;
deg[v]++;
sz++;
E[sz].from=u;
E[sz].to=v;
E[sz].next=head[u];
head[u]=sz;
}
int dp[maxn];//表示离x最近的叶子节点到x的距离
//不能从一个根开始DFS,因为此时根不定,
//到一个点最近的叶子节点不一定在DFS时的子树里,而可能在它上方
void bfs(){
queue<int>q;
for(int i=1;i<=n;i++){
if(deg[i]<=1){
q.push(i);
dp[i]=0;
}else dp[i]=INF;
}
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(dp[y]==INF){
dp[y]=min(dp[y],dp[x]+1);
q.push(y);
}
}
}
}
int s,t,d;
void dfs2(int x,int fa,int deep){
if(fa!=0&°[x]!=2){
s=x;
t=fa;
d=deep;
return;
}
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(y!=fa){
dfs2(y,x,deep+1);
E[i].nto=s;
E[i].nfrom=t;
E[i].len=d-deep;
}
}
}
int ans=0;
void dfs3(int x,int fa,int deep){
if(deep>=dp[x]){
ans++;
return;
}
for(int i=head[x];i;i=E[i].next){
int y=E[i].to;
if(y!=fa){
dfs3(E[i].nto,E[i].nfrom,deep+E[i].len);
}
}
}
int main(){
int u,v;
qread(n);
for(int i=1;i<n;i++){
qread(u);
qread(v);
add_edge(u,v);
add_edge(v,u);
}
for(int i=1;i<=n;i++) deg[i]/=2;
bfs();
for(int i=1;i<=n;i++){
if(deg[i]!=2) dfs2(i,0,0);
}
for(int i=1;i<=n;i++){
ans=0;
dfs3(i,0,0);
qprint(ans);
putchar('\n');
}
}
luogu P4183 Cow at Large P (暴力吊打点分治)(内有时间复杂度证明)的更多相关文章
- [USACO18JAN]Cow at Large G(树形DP)
P4186 [USACO18JAN]Cow at Large G(树形DP) Luogu4186 设dp[i]表示i点需要放多少个农民.则有 \(if(near[i]-dep[i]<=dep[i ...
- luogu P4183 [USACO18JAN]Cow at Large P
传送门 首先考虑N^2做法,每次从一个点出发,如果到达一个点,然后到达这个点的时间\(\le\)离这个点最近的叶子距离\(di_x\),那么答案+1,否则继续找点 这个暴力很不好优化.可以这样认为,如 ...
- [洛谷P4183][USACO18JAN]Cow at Large P
题目链接 Bzoj崩了之后在洛谷偶然找到的点分好题! 在暴力的角度来说,如果我们$O(n)$枚举根节点,有没有办法在$O(n)$的时间内找到答案呢? 此时如果用树形$dp$的想法,发现是可做的,因为可 ...
- 洛谷 P4183 - [USACO18JAN]Cow at Large P(点分治)
洛谷题面传送门 点分治 hot tea. 首先考虑什么样的点能够对以 \(u\) 为根的答案产生 \(1\) 的贡献.我们考虑以 \(u\) 为根对整棵树进行一遍 DFS.那么对于一个点 \(v\), ...
- [USACO18JAN]Cow at Large P
Description: 贝茜被农民们逼进了一个偏僻的农场.农场可视为一棵有 \(N\) 个结点的树,结点分别编号为 \(1,2,\ldots, N\) .每个叶子结点都是出入口.开始时,每个出入口都 ...
- Codeforces Round #312 (Div. 2)B. Amr and The Large Array 暴力
B. Amr and The Large Array Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contes ...
- [LOJ#2386]. 「USACO 2018.01 Platinum」Cow at Large[点分治]
题意 题目链接 分析 假设当前的根为 rt ,我们能够在奶牛到达 \(u\) 之时拦住它,当且仅当到叶子节点到 \(u\) 的最短距离 \(mn_u \le dis_u\) .容易发现,合法的区域是许 ...
- P4186 【[USACO18JAN]Cow at Large G】
思路是覆盖子树,我们发现,农民想截住牛的最优策略是不断向上来尽可能地覆盖更大的子树 我们想要尽早地覆盖一个子树,一个显然的贪心是在这个子树中选取深度最小的一个放农民 如果我们在一个点放置了农民,那么其 ...
- BZOJ5189: [Usaco2018 Jan]Cow at Large 贪心+LCA
BZOJ没有题面QAQ,题目链接 洛谷有:题目链接 这题首先要读懂题..(洛谷的翻译有点迷 就是指定根节点,然后可以在叶子结点放个人,然后奶牛在根,问最少要在叶子结点放多少人才能让奶牛走不到叶子结点( ...
随机推荐
- 【学习总结】cpu缓存
参考链接: cpu缓存java性能问题初探 高速缓存 在内存与cpu寄存器之间,还有一块区域叫做cpu高速缓存,即我们常常说的cache. cache分为L1.L2.L3三级缓存,速度递减,离cpu越 ...
- 【JAVA】 01-Java基础知识
链接: 笔记目录:毕向东Java基础视频教程-笔记 GitHub库:JavaBXD33 测试 01-Java基础知识 一.数据类型 基本类型 包装类型 缓存池 二.String 概览 不可变的好处 S ...
- JS书目推荐(私教推荐)
下面几本书是私教推荐的,从入门到提高,从易到难,想找电子版的可以去下面这个网站找找,挺多书籍的 鸠摩搜书https://www.jiumodiary.com/ JavaScript编程精解 (第二版) ...
- proc - 进程信息伪文件系统
描述 /proc 是一个伪文件系统, 被用作内核数据结构的接口, 而不仅仅是解释说明 /dev/kmem. /proc里的大多数文件都是只读的, 但也可以通过写一些文件来改变内核变量. 下面对整个 / ...
- 吉首大学2019年程序设计竞赛(重现赛) J 滑稽树下你和我 (递归)
链接:https://ac.nowcoder.com/acm/contest/992/J来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K ...
- C#基础知识之类和结构
虽然项目中一直在使用类.结构体等类型,仔细琢磨,还真无法系统的说出个所以然.记录一下类.结构体.类和结构体区别 一.类 对于类,大家都特别熟悉.简单的介绍一下类的结构,然后记录一下Class需要注意的 ...
- RabbitMQ:伪延时队列
目录 一.什么是延时队列 二.RabbitMQ实现 三. 延时队列的问题 四.解决RabbitMQ的伪延时方案 ps:伪延时队列先卖个关子,我们先了解下延时队列. 一.什么是延时队列 所谓延时队列是指 ...
- Vue.js----date与时间戳的转换(unixTime)Moment.js让日期处理变得更简单
当前日期格式化 let curTime = moment().format('YYYY-MM-DD HH:mm:ss') console.log('当前日期时间curTime:' + curTime) ...
- HDU 5667 构造矩阵快速幂
HDU 5667 构造矩阵快速幂 题目描述 解析 我们根据递推公式 设 则可得到Q的指数关系式 求Q构造矩阵 同时有公式 其中φ为欧拉函数,且当p为质数时有 代码 #include <cstdi ...
- 【BZOJ1396】识别子串(后缀自动机,线段树)
题意: 一行,一个由小写字母组成的字符串S,长度不超过10^5 思路:论文题 设p为自动机上的合法结点,r为右端点,len=st[fa[p]]]+1 位置[r-st[p]+1,r-len+1]与r-i ...