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

news2024/11/25 11:05:12

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.coloradmin.cn/o/849643.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pytest之测试用例执行顺序

前言 在unittest框架中&#xff0c;默认按照ACSII码的顺序加载测试用例并执行&#xff0c;顺序为&#xff1a;09、AZ、a~z&#xff0c;测试目录、测试模块、测试类、测试方法/测试函数都按照这个规则来加载测试用例。 而 pytest 中的用例执行顺序与unittest 是不一样的&#…

CTF流量题解http4.pcapng

流量分析 导出http 打开报错 验证文件头&#xff0c;发现是zip。 图常片见里文可件能的包16含进:压制缩头包部,word,pdf JPG FF D8 FF E0/FF D8 FF E1 PNG 89 50 4E 47 GIF 47 49 46 38 ZIP 50 4B 03 04 RAR 52 61 72 21 MP3 49 44 33 0 改后缀 使用工具爆破。 git clone git…

牛客周赛 Round 6

A 游游的数字圈 题目大意 给定一个由数字字符组成的字符串&#xff0c;统计该字符串中出现的圆圈数量。其中数字0、6、9各有一个圆圈&#xff0c;数字8有两个圆圈。 思路分析 遍历字符串中的每个字符&#xff0c;对于每个字符&#xff0c;判断其是0、6、9则加1&#xff0c;是…

网络安全--mysql中事务锁以及事务隔离解析

一、事务锁 1、个人理解&#xff1a; 专一性和历史性&#xff0c;例如一个男人历史上是花心的&#xff0c;但当他成长后开启begin和update后变的专一了&#xff0c;多项事务也影响不到他了&#xff0c;直到水泥封心&#xff0c;只可被一个人查询在此我们进入正题&#xff1a;…

【代码】表格封装 + 高级查询 + 搜索 +分页器 (极简)

一、标题 查询条件按钮&#xff08;Header&#xff09; <!-- Header 标题搜索栏 --> <template><div><div class"header"><div class"h-left"><div class"title"><div class"desc-test">…

《动手学深度学习》优化算法学习习题

优化算法 梯度下降类 小批量随机梯度下降&#xff0c;通过平均梯度来减小方差 动量法 基础 泄露平均法&#xff1a;用来取代梯度的计算 β \beta β这个参数控制了取多久时间的平均值 上述推理构成了”加速”梯度方法的基础&#xff0c;例如具有动量的梯度。 在优化问题…

SpringMVC的架构有什么优势?——视图与模型(二)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

Codeforces Round 891 (Div. 3)

Array ColoringArray Coloring 题目大意 题目要求判断是否可以将数组元素分为两种颜色&#xff0c;使得两种颜色元素的和具有相同的奇偶性&#xff0c;并且每种颜色至少有一个元素被着色。 思路分析 可以通过统计数组中奇数和偶数的个数来判断是否满足条件。分析可知&#x…

论文阅读---《Unsupervised ECG Analysis: A Review》

题目 无监督心电图分析一综述 摘要 电心图&#xff08;ECG&#xff09;是检测异常心脏状况的黄金标准技术。自动检测心电图异常有助于临床医生分析心脏监护仪每天产生的大量数据。由于用于训练监督式机器学习模型的带有心脏病专家标签的异常心电图样本数量有限&#xff0c;对…

Redis BitMap/HyperLogLog/GEO/布隆过滤器案例

面试问题&#xff1a; 抖音电商直播&#xff0c;主播介绍的商品有评论&#xff0c;1个商品对应了1系列的评论&#xff0c;排序展现取前10条记录用户在手机App上的签到打卡信息&#xff1a;1天对应1系列用户的签到记录&#xff0c;新浪微博、钉钉打卡签到&#xff0c;来没来如何…

模拟实现消息队列项目(系列7) -- 实现BrokerServer

目录 前言 1. 创建BrokerServer类 1.1 启动服务器 1.2 停止服务器 1.3 处理一个客户端的连接 1.3.1 解析请求得到Request对象 1.3.2 根据请求计算响应 1.3.3 将响应写回给客户端 1.3.4 遍历Session的哈希表,把断开的Socket对象的键值对进行删除 2. 处理订阅消息请求详解(补充) …

树、森林 与 二叉树

树、森林 与 二叉树 树结构树结构的基本概念根节点子节点父节点叶节点兄弟节点子树深度高度 树结构的特点二叉树森林查找与遍历方法查找深度优先搜索广度优先搜索 遍历前序遍历中序遍历后序遍历 应用场景 树结构 树结构是一种非常常见且重要的数据结构&#xff0c;它模拟了自然…

中间件RabbitMQ消息队列介绍

1. MQ的相关概念 1.1 什么是MQ MQ&#xff08;message queue&#xff09;&#xff0c;从字面意思上看&#xff0c;本质是个队列&#xff0c;FIFO先入先出&#xff0c;只不过队列中存放的内容是message而已&#xff0c;还是一种跨进程的通信机制&#xff0c;用于上下游传递消息…

Python Opencv实践 - 在图像上绘制图形

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png") print(img.shape)plt.imshow(img[:,:,::-1])#画直线 #cv.line(img,start,end,color,thickness) #参考资料&#xff1a;https://blog.csdn.ne…

【NLP】深入浅出全面回顾注意力机制

深入浅出全面回顾注意力机制 1. 注意力机制概述2. 举个例子&#xff1a;使用PyTorch带注意力机制的Encoder-Decoder模型3. Transformer架构回顾3.1 Transformer的顶层设计3.2 Encoder与Decoder的输入3.3 高并发长记忆的实现self-attention的矩阵计算形式多头注意力&#xff08;…

三次握手与四次挥手 tcp协议特点 tcp状态转移图 TIME_WAIT 抓包

讲解 三次握手图示理解讲解 四次挥手图示理解理解 tcp协议特点tcp状态转移过程总图四次挥手状态转移过程三次挥手状态转移过程 TIME_WAIT状态存在的原因连接状态的一个测试一个面试题&#xff1a;抓包&#xff1a; 三次握手 图示理解 三次握手发生在客户端执行 connect()的时…

elfk

1. 2. ​​​​​​​ 3. 4. 5.

UML—浅谈常用九种图

目录 概述: 1.用例图 2.静态图 3.行为图&#xff1a; 4.交互图&#xff1a; 5.实现图&#xff1a; 概述: UML的视图是由九种视图组成的&#xff0c;分别是用例图、类图、对象图、状态图、活动图、序列图、协作图、构件图、实施图。我们可以根据这9种图的功能和实现的目的…

redis是单线程的,那么他是怎么样避免阻塞的

Redis 实例有哪些阻塞点&#xff1f; Redis 实例在运行时&#xff0c;要和许多对象进行交互&#xff0c;这些不同的交互就会涉及不同的操作&#xff0c;下 面我们来看看和 Redis 实例交互的对象&#xff0c;以及交互时会发生的操作。 客户端&#xff1a;网络 IO&#xff0c;键…

springboot scheduling实现定时任务

文章目录 springboot实现定时任务开启springboot定时任务原因分析&#xff1a; 配置线程池&#xff0c;让定时任务指定并发执行先要线程异步执行springboot异步线程池设置指定线程池执行任务 springboot实现定时任务 开启springboot定时任务 springboot实现定时任务很简单&am…