题意:

题目传送门

  • 在一棵 n 个结点的树上,有 k 个贪吃虫去吃食物。
  • 每个贪吃虫都走到达食物的唯一路径。
  • 当一条贪吃虫通向食物的道路上有另一条贪吃虫,则较远的那只停止移动。
  • 多条贪吃虫要进入同一节点时,编号最小的才能进入,其他的停止移动。
  • 贪吃虫的移动速度皆为 1。一只贪吃虫吃到食物后,另一个食物立刻出现在树上,贪吃虫继续按以上规则移动。
  • 最后求出每条贪吃虫所在的位置与吃到食物的数量。

思路:

可以把每一个食物看成一个测试点。那么就是要计算出每个节点被哪条贪吃虫占领和每条贪吃虫最终停留的地方。

很明显,对于这两个要计算的值,可以通过两次 dfs 来求。

第一次 dfs。对于每一个节点,占领它的贪吃虫一定是到达用时最短的那个。到达它的最短的时间就是最短的子节点到达时间 +1。还要注意两种特殊情况,在代码里也会有说明:

  1. 该点已有贪吃虫。

  2. 有速度相同,取编号最小的贪吃虫。

结束后把占领食物所在节点的贪吃虫吃到的食物数 +1。

第二次 dfs 时,可以利用第一次求出的值取计算。因为在第一次 dfs 时,我们求出了占领每个节点所用的时间,所以可以用一个数组去记录每一条贪吃虫到达最终落脚点的时间,这个值是可以算出的。如果对于某个节点,占据他的贪吃虫到达最终落脚点的时间 = 该节点被占领的时间,则该节点为这条贪吃虫的最终落脚点。

代码:

请勿抄袭。

#include<bits/stdc++.h>
using namespace std;
int n,k,h;
//n,k,h与题中含义一致
struct stu{
int nxt,to;
}e[10010];
int cnt;
int head[10010];
//以上为链式前向星存图
int b[5001];//每一条贪吃虫所在节点
int p[5001];//每个节点上为哪条贪吃虫,0表示没有贪吃虫
int c[501];//每一次食物出现的地方
int eat[5001];//每条贪吃虫吃的食物数
int t[5001];//占领每个节点的时间
int o[5001];//每个节点被占据的贪吃虫编号
int f[5001];//题解中第二次搜索用来记录的数组
inline void add(int x,int y)//建边
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
head[x]=cnt;
}
inline void dfs1(int now,int fa)//第一次搜索,求出每个节点被哪条贪吃虫占据
//now为当前搜索到的节点,fa为上一次搜索的节点,避免重复搜索
{
int mp,mt;//记录占领该节点的时间与贪吃虫编号
if(p[now])//该点上已有贪吃虫
{
mp=p[now];//占领的贪吃虫即为该节点上的贪吃虫
mt=0;//占领速度为0
}
else //否则因为要取最小值,所以设一个大的数
{
mp=9999;
mt=9999;
}
for(int i=head[now];i;i=e[i].nxt)//依次搜索每一个儿子
{
int to=e[i].to;
if(to==fa) continue;//避免重复搜索
dfs1(to,now);
if((t[to]+1)<mt||((t[to]+1)==mt&&o[to]<mp))
//时间更短或时间相同并且编号较小即可更新
{
mt=t[to]+1;
mp=o[to];
}
}
t[now]=mt;
o[now]=mp;
//保存计算后的值
}
inline void dfs2(int now,int fa)//第二次搜索,计算每一只贪吃虫最终落脚点
//参数意义与dfs1一致
{
if(o[now]!=9999)//=9999说明没有贪吃虫来过,没必要计算
{
if(f[o[now]]==-1&&o[fa]!=o[now])
//没有计算过,后面的条件是因为贪吃虫一样,那么f[o[now]]没计算过,f[o[fa]]也一定没计算过
{ //计算,取三种可能时间的最小值
int mt=min(t[fa],t[now]);
f[o[now]]=min(f[o[fa]],mt);
}
if(f[o[now]]!=-1&&f[o[now]]==t[now]) b[o[now]]=now;//计算过且时间一致,则该点为这条贪吃虫的最终落脚点
}
for(int i=head[now];i;i=e[i].nxt)//继续搜索子节点
{
int to=e[i].to;
if(to==fa) continue;//同理,防重
dfs2(to,now);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)//读入这棵树,并建树(边)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);//建双向边
}
scanf("%d",&k);
for(int i=1;i<=k;i++)//记录每一条贪吃虫的位置
{
int x;
scanf("%d",&x);
p[x]=i;
b[i]=x;//按照数组含义记录
}
scanf("%d",&h);
for(int i=1;i<=h;i++)//读入每一次食物出现的位置
{
scanf("%d",&c[i]);
}
for(int i=1;i<=h;i++)
{
memset(t,0,sizeof(t));
memset(o,0,sizeof(o));
memset(f,-1,sizeof(f));//由于数组内还有上一次循环的值,因此将其初始化
dfs1(c[i],-1);//搜索
++eat[o[c[i]]];//将吃到食物的贪吃虫更新
f[o[c[i]]]=t[c[i]];//吃到食物的贪吃虫最终落脚点即为食物处
//因此到达最终落脚点的位置即为到达食物的位置
//这里也是为了下面的搜索的计算
dfs2(c[i],-1);
memset(p,0,sizeof(p));//由于这一轮过后贪吃虫又有了新的位置,因此先将旧的清零,并更新
for(int j=1;j<=k;j++)
{
p[b[j]]=j;
}
}
for(int i=1;i<=k;i++)//输出答案
{
printf("%d %d\n",b[i],eat[i]);
}
return 0;
}

写题解不易,点个赞呗。

P1751 贪吃虫 题解的更多相关文章

  1. 游戏:贪吃虫(GreedyMaggot)

    该游戏类似于贪吃蛇,但可以在二维平面上以任意方向前进.当吃到食物手,食物会从虫头向虫尾移动,移到虫尾后,贪吃虫长度会增加.本来给它取名为贪吃蛆的,并且工程的英文名Maggot就是蛆的意思,后来想想有点 ...

  2. 洛谷P7078 [CSP-S2020] 贪吃蛇 题解

    比赛里能做出这题的人真的非常厉害,至少他的智商和蛇一样足够聪明. 首先有一个结论: 当前最强的蛇吃了最弱的蛇之后,如果没有变成最弱的蛇,他一定会选择吃! 证明: 假设当前最强的蛇叫石老板. 如果下一条 ...

  3. Hadoop企业级应用

    Hadoop专业解决方案之构建Hadoop企业级应用 一.大数据的挑战 大数据面对挑战是你必须重新思考构建数据分析应用的方式.传统方式的应用构建是基于数据存储在不支持大数据处理的基础之上.这主要是因为 ...

  4. WhyEngine游戏合集2014贺岁版

    WhyEngine游戏合集2014贺岁版 自去年9月份开始写我的第一个小游戏,到现在为止,共实现了14个小游戏,10个屏保程序,7个DEMO程序.开发环境是VS2008,渲染使用的是D3D,所有代码都 ...

  5. Why游戏作品合集

    之前曾经发过一个套WhyEngine游戏作品合集,里面有十几个小游戏和若干个屏保程序和若干个DEMO程序.而这次发的与上次不一样,因为这是我花了两天时间将所有的程序集成到一个工程后的成果.为了能将所有 ...

  6. WhyEngine游戏引擎作品合集

    从9月份开始写三个月内总共实现了13个游戏,5个屏保程序,5个DEMO程序.如果运行时,报有木马病毒什么的,请相信我,这绝对是杀毒软件的误报,自己写的程序由于没有得到杀毒软件的认证,被报有危险是正常的 ...

  7. 【NOIp2004提高组】食虫算 题解

    所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 + 8468#6633 44445509678 其中#号代表被 ...

  8. 【题解】 P1092虫食算

    [题解]P1092 虫食算 老题了,很经典. 用到了一些搜索套路. 可行性剪枝,劣者靠后,随机化,\(etc......\) 搜索设参也很有技巧,设一个\(adjustment\)参数可以很方便地在两 ...

  9. 【题解】ZJOI2010贪吃的老鼠

    %%%%真的好强...看题解我都看了好久才完全明白.放一下参考的博客,谢谢神犇QAQ 1号博客    2号博客(超级赞的啦) 因为理解的过程太艰辛,所以必须记录一下这道强题:这道题目最难的两个约束就在 ...

  10. NOIP 2004 虫食算题解

    问题 E: [Noip2004]虫食算 时间限制: 1 Sec  内存限制: 128 MB 题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一 ...

随机推荐

  1. HashMap和ConcurrentHashMap扩容过程

    HashMap 存储结构 HashMap是数组+链表+红黑树(1.8)实现的. (1)Node[] table,即哈希桶数组.Node是内部类,实现了Map.Entry接口,本质是键值对. 下图链表中 ...

  2. freeswitch媒体协商的优先级方案

    概述 freeswitch是一款简单好用的VOIP开源软交换平台. 不同的媒体格式各有优缺点,实际环境中的应用要根据线路和客户的实际需求确定. 本文中介绍一种较为通用的媒体配置方案,可以适配大部分场景 ...

  3. 【踩坑系列】发送微信模板消息返回40165 invalid weapp pagepath

    1. 踩坑经历 最近做了个需求,需要往公司微信公众号推送一个模板消息,并且点击该消息需要跳转到公司小程序的某个页面. 1.1 拿到模板id 既然是发送模板消息,第一步就需要登录微信公众号后台新建模板消 ...

  4. Alchemy Nft黑客松任务(第一周)

    Alchemy是什么项目? 2019年12月,Alchemy完成1500万美元A轮融资,资方为Pantera Capital,斯坦福大学,Coinbase,三星等. 2021年4月,Alchemy以5 ...

  5. Java面向对象--接口和多态

    final 关键字 最终修饰符 可以修饰 类 方法 变量 被final修饰后不能被继承 重写 二次赋值 修饰类时 该类不可以被继承 修饰方法时 该方法不能被重写 修饰变量时, 该变量只能赋值一次, 不 ...

  6. 迁移学习(TSRP)《Improving Pseudo Labels With Intra-Class Similarity for Unsupervised Domain Adaptation》

    论文信息 论文标题:Improving Pseudo Labels With Intra-Class Similarity for Unsupervised Domain Adaptation论文作者 ...

  7. 在k8s上安装Harbor

    在k8s上安装Harbor 先前条件 <kubernetes(k8s) 存储动态挂载><在k8s(kubernetes)上安装 ingress V1.1.3> 参考我之前的文档 ...

  8. pandas之excel操作

    Excel 是由微软公司开发的办公软件之一,它在日常工作中得到了广泛的应用.在数据量较少的情况下,Excel 对于数据的处理.分析.可视化有其独特的优势,因此可以显著提升您的工作效率.但是,当数据量非 ...

  9. [Windows]CMD命令入门教程 与 Windows常见维护问题

    本博文最早是记录在本地电脑的,由于清理电脑的缘故,顺便将这篇笔记转移到公共博客,以便日后查阅和快速上手使用. 开门见山,步入正题,以下是Windows系统的常用CMD命令. ----2018-03-2 ...

  10. AutoGPT目前只是成功学大师GPT版

    一大波韭菜被收割了 最近很多人在交流对于AutoGPT的震惊和激动.AutoGPT是一个开源的应用程序,展示了GPT-4语言模型的能力.这个程序由GPT-4驱动,自主地开发和管理业务,以增加净值.它是 ...