H. HEX-A-GONE Trails 2023“钉耙编程”中国大学生算法设计超级联赛(7)hdu7354

Problem - 7354

题目大意:有一棵n个点的树,A和B分别从点x,y开始,每轮可以移动到一个相邻节点,但如果某个节点有人访问过,则两人都不能访问那个节点,先没有点可走的人输,问A有没有必胜策略赢

2<=n<=1e5

思路:要想赢,就要走的点数别对方多,因为树上没有走回头路,所以一定要往最长链走才能赢,例如下图这幅图:

我们令A的起点是2,B的起点是9,连接他们的简单路我们称为“关键路径”,我们看先手的A,它可能到达的点只有1~8号点,1能走的所有链的长度d1为[1,1,3,5](按从近到远排序),9能走的所有链的长度d2=[2,3,3,3],同样按到9的距离排序,他当前的最优策略应该是看它左边的子树也就是无法被B干扰的点,如果在这棵子树中存在一条链,它的长度大于所有从9出发的链,那么A一定必胜,不需要考虑B怎么做,但在此图中不存在此情况,所以它要向更长的链也就是向右移动一格到3,接下来轮到B,B的策略也类似,但区别在于因为他是后手,所有只要存在这样一条链长度大于等于从2出发的所有链,就能必胜,此图也不存在此情况

来到下一轮,由于A、B位置改变,已经讨论过的走自子链就没有用了,更新新的图如下:

接下来和上一轮同理,A从3出发,优先走不会受B影响的点,也就是除了关键路径和已访问过的路径的其他路径,如果存在一条路径长度>从6出发的所有链的长度,那么他必胜,此图不符,轮到B,依然同理,发现6~8这条路长度为2,而从3出发的最长路3~5也是2,所以B有了必胜策略,游戏结束。我们按照此策略循环,看谁先找到最优策略,或者两个人汇合时,谁不能继续走。

所以知道了最优策略,我们现在要求关键路径,可以一个dfs实现,然后要求关键路径上的所有点到关键路径以外的所有链中最长链的长度,也可以一个dfs求出,对于一个关键路径上的点u,如果子节点v不在关键路径上,维护dis[u]=max(dis[u],dis[v])即可。然后我们还要求从关键路径上每个点出发的所有链的长度,每移动一个节点,所有从起点出发的链的长度都要-1,但其实可以数学一下,我们求出两个起点出发所有链的长度d1,d2,然后假如A从起点移动了一格,到了编号为i1的点,那么再判断时我们只需要判断dis[i1]+1与从B的起点出发所有链的长度即可,省去了全部-1的操作,我们用st表求最大值即可

#include<bits/stdc++.h>
//#include<__msvc_all_public_headers.hpp>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int n;
int head[N];
struct Edge
{int v, next;
}e[N * 2];
int cnt = 0;
int path[N];
int s1, s2;
int d[N];
void addedge(int u, int v)
{e[++cnt].v = v;e[cnt].next = head[u];head[u] = cnt;
}//邻接链表存树
int rmqmax[N][18];
int rmqmax2[N][18];
void init(int n)
{//初始化for (int i = 0; i <= n; i++){d[i] = 0;head[i] = -1;rmqmax[i][0] = 0;rmqmax2[i][0] = 0;}cnt = 0;
}
void findpath(int u, int fa)
{//找到AB之间的简单路径for (int i = head[u]; ~i; i = e[i].next){int v = e[i].v;if (v == fa)continue;path[v] = u;if (v == s2){return;}findpath(v, u);}
}
map<int, bool>inp;
void dfs(int u, int fa)
{for (int i = head[u]; ~i; i = e[i].next){int v = e[i].v;if (v == fa)continue;dfs(v, u);if (inp.find(v) == inp.end())d[u] = max(d[u], d[v]);//对于不在关键路径上的子链,维护最大值}d[u] += 1;
}
void rmqinit(int n)
{for (int j = 1; (1 << j) <= n; j++){//j代表区间长度,以2的j次幂为单位for (int i = 1; i + (1 << j) - 1 <= n; i++){//i是区间起点,i+2的n次方减一是区间终点rmqmax[i][j] = max(rmqmax[i][j - 1], rmqmax[i + (1 << j - 1)][j - 1]);//求从i开始长2的j次方的区间的最大值和从i+2的j-1次方开始,长2的j次方的区间的最大值的最大值rmqmax2[i][j] = max(rmqmax2[i][j - 1], rmqmax2[i + (1 << j - 1)][j - 1]);}}
}
int rma(int l, int r)
{int k = log2l(r - l + 1);//求区间长度是2的几次幂return max(rmqmax[l][k], rmqmax[r - (1 << k) + 1][k]);//求左端点开始长k的区间的最大值,和从右端点减2的k次方+1的开始,长度为k的区间的最大值的最大值
}
int rma2(int l, int r)
{int k = log2l(r - l + 1);//求区间长度是2的几次幂return max(rmqmax2[l][k], rmqmax2[r - (1 << k) + 1][k]);//求左端点开始长k的区间的最大值,和从右端点减2的k次方+1的开始,长度为k的区间的最大值的最大值
}
int main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);int t;cin >> t;while (t--){int n;cin >> n;inp.clear();init(n);cin >> s1 >> s2;for (int i = 1; i <= n - 1; i++){int u, v;cin >> u >> v;addedge(u, v);addedge(v, u);}findpath(s1, 0);vector<int>p;int now = s2;while (now != s1){inp[now] = 1;//标记在关键路径上的点p.push_back(now);//记录在关键路径上的点now = path[now];}inp[s1] = 1;p.push_back(s1);dfs(s1, 0);vector<int>dis;for (int i = 0; i < p.size(); i++){//记录关键路径上所有点的最长子链长度dis.push_back(d[p[i]] - 1);}int len = dis.size();vector<int>d1(len), d2(len);for (int i = 0; i < len - 1; i++){//从B的起点出发的所有链的长度d2[i] = dis[i] + i;}d2[len - 1] = dis[len - 1];for (int i = len - 1; i > 0; i--){//从A的起点触发的所有链的长度d1[len - i - 1] = dis[i] + len - i - 1;}d1[len - 1] = dis[0];for (int i = 0; i < len-1; i++){//st表维护链长的最大值rmqmax[i + 1][0] = d1[i];rmqmax2[i + 1][0] = d2[i];}rmqinit(len-1);int cnt1 = 0, cnt2 = 0;int it1 = 0, it2 = 0;bool ans = 1;while (1){int temp = rma2(1, len - it1 - 1);//从B的当前点出发的所有链的最大长度if (dis[len - it1 - 1] + cnt1 > temp){//从这个点出发的最长子链长度加上已经走过的步数ans = 1;break;}it1++;cnt1++;if (it1 + it2 == p.size()){//两个点汇合了,下一个人没法走了ans = 1;break;}temp = rma(1, len - it2 - 1);//从A的当前点出发的所有链的最大长度if (dis[it2] + cnt2 >= temp){ans = 0;break;}it2++;cnt2++;if (it1 + it2 == p.size()){ans = 0;break;}}cout << ans << endl;}return 0;
}
//100
//7
//2 3
//6 2
//2 5
//5 1 5 4
//4 3
//3 7
// 
//11
//2 9
//1 2
//2 3
//3 4
//4 5
//4 6
//6 7
//7 8
//6 9
//9 10
//10 11
//
//4
//1 2
//1 2
//3 1
//4 3
//
//4
//1 2
//1 2
//2 3
//3 4
//
//4
//1 4
//1 2 2 3 3 4
//
//5
//1 2
//1 2
//1 3
//3 4
//2 5

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/81266.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode:Hot100的python版本

94. 二叉树的中序遍历

DOM基础获取元素+事件基础+操作元素

一.DOM简介 DOM&#xff0c;全称“Document Object Model&#xff08;文档对象模型&#xff09;”&#xff0c;它是由W3C定义的一个标准。 在实际开发中&#xff0c;我们有时候需要实现鼠标移到某个元素上面时就改变颜色&#xff0c;或者动态添加元素或者删除元素等。其实这些效…

SpringBoot复习:(22)ConfigurationProperties和@PropertySource配合使用及JSR303校验

一、配置类 package cn.edu.tju.config;import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.PropertySource; import org.springframework.stereotype.Component;Component ConfigurationPropertie…

CentOS软件包管理rpm、yum

一、软件包概述 Linux常见软件包分为两种&#xff0c;分别是源代码包、二进制文件包。源代码包是没有经过编译的包&#xff0c;需要经过GCC、C编译器编译才能运行&#xff0c;文件内容包含源代码文件&#xff0c;通常以.tar.gz、.zip、.rar结尾&#xff1b;二进制包无需编译&am…

数据结构 二叉树(一篇基本掌握)

绪论 雄关漫道真如铁&#xff0c;而今迈步从头越。 本章将开始学习二叉树&#xff08;全文共一万两千字&#xff09;&#xff0c;二叉树相较于前面的数据结构来说难度会有许多的攀升&#xff0c;但只要跟着本篇博客深入的学习也可以基本的掌握基础二叉树。 话不多说安全带系好&…

31 对集合中的字符串,按照长度降序排列

思路&#xff1a;使用集合的sort方法&#xff0c;新建一个Comparator接口&#xff0c;泛型是<String>&#xff0c;重写里面的compare方法。 package jiang.com; import java.util.Arrays; import java.util.Comparator; import java.util.List;public class Practice4 {…

在tensorflow分布式训练过程中突然终止(终止)

问题 这是为那些将从服务器接收渐变的员工提供的培训功能&#xff0c;在计算权重和偏差后&#xff0c;将更新的渐变发送到服务器。代码如下&#xff1a; def train():"""Train CIFAR-10 for a number of steps."""g1 tf.Graph()with g1.as_de…

高绩效项目管理助力企业数字化变革︱海克斯康数字智能大中华区PMO经理周游

海克斯康数字智能大中华区PMO经理周游先生受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾&#xff0c;演讲议题&#xff1a;高绩效项目管理助力企业数字化变革。大会将于8月12-13日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&#xff1a; 在当今项目驱动的…

【软件工程】3 ATM系统的设计

目录 3 ATM系统的设计 3.1体系结构设计 3.2 设计模式选择 3.3 补充、完善类图 3.4 数据库设计 3.4.1 类与表的映射关系 3.4.2 数据库设计规范 3.4.3 数据库表 3.5 界面设计 3.5.1 界面结构设计 3.5.2 界面设计 3.5.2.1 功能界面设计 3.5.2.2 交互界面 总博客&…

机器学习笔记

文章目录 编码器-解码器Batch Normalization好处 编码器-解码器 第二个input与transformer中的解码器类似。 Batch Normalization 尽量使得w1和w2之间呈现为正圆 训练模型的时候&#xff0c; μ \mu μ和 σ \sigma σ不可以认为是常数&#xff0c;而是包含数据的变量&…

Stable Diffusion - 哥特 (Goth) 风格服装与背景的 LoRA 配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132177882 图像来源于 Goth Clothing 的 LoRA 效果&#xff0c;配合哥特 (Goth) 风格服饰的相关提示词。 测试模型&#xff1a;DreamShaper 8 哥…

Linux 权限

1. shell命令及其运行原理 1.1 是什么shell&#xff1f; shell是一个命令行解释器。 1.2 shell的作用&#xff1f; 在Linux操作系统中&#xff0c;用户一般是不与操作系统直接交互的&#xff0c;而是通过一个外壳程序来传递用户的需求和反馈结果给用户&#xff0c;shell就是一…

c++:day4

1.思维导图 2.shell函数获取uid和gid&#xff0c;并用变量接 #!/bin/bashfunction fun() {read -p "输入用户名" necho uid:id -u $necho gid:id -g $n } afun echo $a3.冒泡、选择和快排代码整理 /**************************************************************…

ChatGPT下架官方检测工具,承认无法鉴别AI内容

去年底&#xff0c;OpenAI 推出的 ChatGPT &#xff0c;带来了生成式人工智能涌现的热潮。它不仅能够协助完成撰写邮件、视频脚本、文案、翻译、代码等任务&#xff0c;还能通过学习和理解人类的语言来进行对话&#xff0c;并根据聊天的上下文进行互动。 但随之而来的争议也让人…

神码ai火车头伪原创插件怎么用【php源码】

本篇文章给大家谈谈python小程序代码50 到100行&#xff0c;以及python小程序代码100行&#xff0c;希望对各位有所帮助&#xff0c;不要忘了收藏本站喔。 火车头采集ai伪原创插件截图&#xff1a; 目录 1 新建文件夹 2 获取指定文件或文件夹的绝对路径 3 删除指定路径的文件 …

中文版开源Llama 2同时有了语言、多模态大模型,完全可商用

可以说&#xff0c;AI 初创公司 LinkSoul.Al 的这些开源项目让海外开源大模型在国内的普及和推广速度与国际几乎保持了一致。 7 月 19 日&#xff0c;Meta 终于发布了免费可商用版本 Llama 2&#xff0c;让开源大模型领域的格局发生了巨大变化。 Llama 2 模型系列包含 70 亿、…

使用docker搭建GPT服务

不用ChatGPT账号,不用API,直接免费使用上官方原版的GPT4.0! 这个操作主要使用的是GitHub上的一个开源项目freegpt。 通过docker把这个项目打包到本地电脑上,直接就能使用上原版GPT4.0。 第一步:下载Docker 下载网址:docker.com 根据自己的电脑系统下载对应的版本即可 下…

rk3399移植linux kernel

rk3399移植linux kernel 0.前言一、移植ubuntu根文件系统二、移植linux1.支持NFS(可选)2.配置uevent helper3.支持etx4文件系统(默认已支持)4.配置DRM驱动5.有线网卡驱动6.无线网卡驱动 三、设备树四、内核镜像文件制作五、烧录六、总结 参考文章&#xff1a; 1.RK3399移植u-bo…

python高阶技巧

目录 设计模式 单例模式 具体用法 工厂模式 优点 闭包 案例 修改闭包外部变量 闭包优缺点 装饰器 装饰器原理 装饰器写法 递归 递归的调用过程 递归的优缺点 用递归计算阶乘 设计模式 含义&#xff1a;设计模式是一种编程套路&#xff0c;通过这种编程套路可…

数字员工助力农行安全生产数字化转型应用实践

党的二十大指出&#xff0c;“以数字中国建设助力中国式现代化&#xff0c;加快建设网络强国、数字中国”&#xff0c;2022年1月发布《“十四五”数字经济发展规划》提出&#xff0c;加强类人智能、自然交互与虚拟现实等技术研究。近年来&#xff0c;各大银行纷纷推出自己的数字…