Description:

贝茜被农民们逼进了一个偏僻的农场。农场可视为一棵有 \(N\) 个结点的树,结点分别编号为 \(1,2,\ldots, N\) 。每个叶子结点都是出入口。开始时,每个出入口都可以放一个农民(也可以不放)。每个时刻,贝茜和农民都可以移动到相邻的一个结点。如果某一时刻农民与贝茜相遇了(在边上或点上均算),则贝茜将被抓住。抓捕过程中,农民们与贝茜均知道对方在哪个结点。

Hint:

\(n \le 7*10^4\)

Solution:

很有趣的题

题解大多是点分治做法

但是由于我的点分治太菜

便学习了这种神仙做法,还跑到了\(luogu\) \(rk5\)?

设牛在rt处出发,现在处于u,并且有叶子v

不难发现我们需要预处理出每个点到它最近叶子节点的距离

然后根据 $dep[rt]-dep[u] \le dep[u]-dep[v] $

来判断这个叶子是否可以放农民来控制它

如果可以,则return,因为越早控制住这个点,答案就越小

首先,显然一条链上的答案都是相等的

所有考虑把链缩成边,再暴力每个点\(dfs\)

这样复杂度就会降下来,不过貌似会被菊花图卡飞?

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const int mxn=7e4+5;
int n,tot,cnt,ans,x,y,w,f[mxn],in[mxn],hd[mxn]; inline int read() {
char c=getchar(); int x=0,f=1;
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
return x*f;
}
inline void chkmax(register int &x,register int y) {if(x<y) x=y;}
inline void chkmin(register int &x,register int y) {if(x>y) x=y;}
queue< int > q;
int ev;
struct ed {
int to,nxt,go,w,fa;
}t[mxn<<1]; inline void add(register int u,register int v) {
t[++cnt]=(ed) {v,hd[u]}; hd[u]=cnt;
} void bfs()
{
for(register int i=1;i<=n;++i)
if(in[i]==1) q.push(i),f[i]=0;
else f[i]=-1;
while(!q.empty()) {
register int u=q.front(); q.pop();
for(register int i=hd[u];i;i=t[i].nxt) {
register int v=t[i].to;
if(f[v]==-1) {
f[v]=f[u]+1;
q.push(v);
}
}
}
} //使用广搜巧妙地处理f数组 void dfs1(register int u,register int fa,register int d) {
if(fa&&in[u]!=2) {x=u,ev=fa,w=d;return ;} //对于每个点只处理它周围的链,保证复杂度
for(register int i=hd[u];i;i=t[i].nxt) {
register int v=t[i].to;
if(v==fa) continue ;
dfs1(v,u,d+1);
t[i].go=x,t[i].fa=ev,t[i].w=w-d; //缩边,细节稍多
}
} void dfs2(register int u,register int fa,register int d)
{
if(f[u]<=d) {
++ans;
return ;
}
for(register int i=hd[u];i;i=t[i].nxt) {
if(t[i].to!=fa)
dfs2(t[i].go,t[i].fa,d+t[i].w); //在新图上算答案
}
} int main()
{
n=read(); register int u,v;
for(register int i=1;i<n;++i) {
u=read(); v=read();
add(u,v); add(v,u);
++in[u]; ++in[v];
}
bfs();
for(register int i=1;i<=n;++i)
if(in[i]!=2) {dfs1(i,0,0);}
for(register int i=1;i<=n;++i) {
if(in[i]==1) {
puts("1");
continue ;
}
ans=0; dfs2(i,0,0);
printf("%d\n",ans);
}
return 0;
}

最新文章

  1. Nginx下wordpress伪静态规则(rewrite)
  2. 实战java虚拟机的学习计划图(看懂java虚拟机)
  3. Struts2.3.15.1源码浅析
  4. codeforces B. Jeff and Periods 解题报告
  5. 1.6.8 Content Streams
  6. Google发布SSLv3漏洞简要分析报告
  7. [Android]应用的前后台运行
  8. mysql 如何修改字符串为 utf8
  9. .NET设计模式(6):原型模式(Prototype Pattern)
  10. vs2008编译wxWidgets 2.8.12
  11. C++多线程二
  12. zipkin
  13. 使用GDB调试gp(转载)
  14. Android 引用外部字体
  15. python 的排名,已经python的简单介绍
  16. docker for mac 安装 kubernetes、kubernetes dashboard
  17. 深入理解 JavaScript 中的函数
  18. SSL certificate problem: unable to get local issuer certificate 的解决方法
  19. GlusterFS实战
  20. 理解URI

热门文章

  1. 沈阳润才教育CRM
  2. 论文阅读笔记二十八:You Only Look Once: Unified,Real-Time Object Detection(YOLO v1 CVPR2015)
  3. 饮冰三年-人工智能-linux-09 服务
  4. 步步为营102-Css样式加个版本
  5. Spark的Streaming + Flume进行数据采集(flume主动推送或者Spark Stream主动拉取)
  6. L1与L2正则(转)
  7. 线程 ID
  8. Python_collections_OrderedDict有序字典部分功能介绍
  9. RocketMQ 启动停止命令
  10. 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。