P4281 [AHOI2008] 紧急集合 / 聚会(内附封面)

[AHOI2008] 紧急集合 / 聚会

题目描述

欢乐岛上有个非常好玩的游戏,叫做“紧急集合”。在岛上分散有 n n n 个等待点,有 n − 1 n-1 n1 条道路连接着它们,每一条道路都连接某两个等待点,且通过这些道路可以走遍所有的等待点,通过道路从一个点到另一个点要花费一个游戏币。

参加游戏的人三人一组,开始的时候,所有人员均任意分散在各个等待点上(每个点同时允许多个人等待),每个人均带有足够多的游戏币(用于支付使用道路的花费)、地图(标明等待点之间道路连接的情况)以及对话机(用于和同组的成员联系)。当集合号吹响后,每组成员之间迅速联系,了解到自己组所有成员所在的等待点后,迅速在 n n n 个等待点中确定一个集结点,组内所有成员将在该集合点集合,集合所用花费最少的组将是游戏的赢家。

小可可和他的朋友邀请你一起参加这个游戏,由你来选择集合点,聪明的你能够完成这个任务,帮助小可可赢得游戏吗?

输入格式

第一行两个正整数 n n n m m m,分别表示等待点的个数(等待点也从 1 1 1 n n n 进行编号)和获奖所需要完成集合的次数。

随后 n − 1 n-1 n1 行,每行两个正整数 a , b a,b a,b,表示编号为 a a a 和编号为 b b b 的等待点之间有一条路。

随后 m m m 行,每行用三个正整数 x , y , z x,y,z x,y,z,表示某次集合前小可可、小可可的朋友以及你所在等待点的编号。

输出格式

输出共 m m m 行,每行两个用空格隔开的整数 p , c p,c p,c。其中第 i i i 行表示第 i i i 次集合点选择在编号为 p p p 的等待点,集合总共的花费是 c c c 个游戏币。

样例 #1

样例输入 #1

6 4  
1 2  
2 3  
2 4 
4 5
5 6
4 5 6
6 3 1
2 4 4 
6 6 6

样例输出 #1

5 2
2 5
4 1
6 0

提示

对于 40 % 40\% 40% 的数据, n ≤ 2 × 1 0 3 n\leq2\times10^3 n2×103 m ≤ 2 × 1 0 3 m\leq2\times 10^3 m2×103

对于 100 % 100\% 100% 的数据, 1 ≤ x , y , z ≤ n ≤ 5 × 1 0 5 1\leq x,y,z\leq n\leq 5\times10^5 1x,y,zn5×105 1 ≤ m ≤ 5 × 1 0 5 1\leq m\leq 5\times 10^5 1m5×105

大致思路

要求出三个点走到同一个点所要求的最小花费,分析后可以得出这个公共的LCA点较其他点优。
求三个点两两之间的LCA,然后这三个LCA中有二者重合的点的另一点即为最优LCA点

QUESTION 1

它存在三种情况:最后三者所走到的最优公共点只可能为这二者之一。
假设我们当前有 X Y Z XYZ XYZ三个点,那么就会有 L C A X Y LCAXY LCAXY L C A X Z LCAXZ LCAXZ L C A Y Z LCAYZ LCAYZ,若其中一组相等,则另一个剩余的为最优点
例: L C A X Y = = L C A Y Z LCAXY==LCAYZ LCAXY==LCAYZ,则最后输出的最优点为 L C A X Z LCAXZ LCAXZ

QUESTION 2

对于深度(由于边权为1,所以深度 = = =花费),我们可以用 X , Y , Z X ,Y ,Z X,Y,Z及其 L C A LCA LCA的深度计算
已知三个点和其LCA的深度,那么LCA相等的两个点走到LCA后,再一起移动到与另一点的LCA的花费是两倍于另一点走到这一个相等的LCA的(两个人走一条路与一个人走一条路的区别,肯定是一个人走花费少)
因此我们可以得出:花费一定与三个点分别的LCA最小值和最大值有关
因为LCA实质上是在树上向上走,所以花费等于三个点深度和减去两倍的LCA最小值,减去一倍的LCA最大值 = = = > ===> ===>
c o s t = d e p [ x ] + d e p [ y ] + d e p [ z ] − m i n ( d e p [ L C A x y ] , d e p [ L C A x z ] , d e p [ L C A y z ] ) ∗ 2 − m a x ( d e p [ L C A x y ] , d e p [ L C A x z ] , d e p [ L C A y z ] ) cost=dep[x]+dep[y]+dep[z]-min(dep[LCAxy],dep[LCAxz],dep[LCAyz])*2-max(dep[LCAxy],dep[LCAxz],dep[LCAyz]) cost=dep[x]+dep[y]+dep[z]min(dep[LCAxy],dep[LCAxz],dep[LCAyz])2max(dep[LCAxy],dep[LCAxz],dep[LCAyz])

AC CODE

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+123;
int n,m,sum=0;
int f[N][24],dep[N],md=-N;
struct node{
	vector<int> ve;
}a[N];
void dfs(int fa,int cnt,int dept){
	if(dep[cnt]!=0)return;
	dep[cnt]=dept;
	f[cnt][0]=fa;
	md=max(md,dept);
	for(auto &x:a[cnt].ve){
		if(dep[x]!=0)continue;
		dfs(cnt,x,dept+1);
	}
}
void LCA(){
	f[1][0]=1;
	for(int i=1;(1<<i)<=md;i++){
		for(int j=1;j<=n;j++){
			f[j][i]=f[f[j][i-1]][i-1];
		}
	}
}
int query(int x,int y){
	sum=0;
	if(dep[x]>dep[y])swap(x,y);
	for(int i=23;i>=0;i--){
		if(dep[f[y][i]]>=dep[x]){
			y=f[y][i];
			sum+=(1<<i);
		}
	}
	if(x==y)return x;
	for(int i=23;i>=0;i--){
		if(f[x][i]!=f[y][i]){
			x=f[x][i];y=f[y][i];
			sum=sum+(1<<i)*2;
		}
	}
	return f[x][0];
}
int main(){
	cin>>n>>m;
	for(int i=1,aa,bb;i<n;i++){
		cin>>aa>>bb;
		a[aa].ve.push_back(bb);
		a[bb].ve.push_back(aa);
	}
	dfs(1,1,1);
	LCA();
	for(int i=1;i<=m;i++){
		int x,y,z;
//		cin>>x>>y>>z;
		scanf("%d%d%d",&x,&y,&z);
		int lxy=query(x,y);
		int lyz=query(y,z);
		int lxz=query(x,z);
		int ans;
		ans=dep[x]+dep[y]+dep[z]-
		min(dep[lxy],min(dep[lxz],dep[lyz]))*2
		-max(dep[lxy],max(dep[lxz],dep[lyz]));
		if(lxy==lxz){//root==y
//			cout<<lyz<<" "<<ans<<endl;
			printf("%d %d\n",lyz,ans);
		}
		else if(lxy==lyz){
//			cout<<lxz<<" "<<ans<<endl;
			printf("%d %d\n",lxz,ans);
		}
		else if(lxz==lyz){
//			cout<<lxy<<" "<<ans<<endl;
			printf("%d %d\n",lxy,ans);
		}
	}
	return 0;
}
/*6 4  
1 2  
2 3  
2 4 
4 5
5 6
6 3 1*/

封面

在这里插入图片描述

  • 30
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,我似乎没有找到与彩旗飘飘Python相关的引用内容。但是,如果你想在Python中实现彩旗飘飘的效果,你可以使用Pygame库来创建动画。以下是一个简单的示例代码,可以帮助你开始: ```python import pygame import random # 初始化pygame pygame.init() # 设置屏幕尺寸 screen_width = 800 screen_height = 600 screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("彩旗飘飘") # 加载彩旗图片 flag_image = pygame.image.load("flag.png") # 获取彩旗图片的宽度和高度 flag_width = flag_image.get_width() flag_height = flag_image.get_height() # 设置彩旗的起始位置 flag_x = screen_width // 2 - flag_width // 2 flag_y = screen_height // 2 - flag_height // 2 # 设置彩旗的速度 flag_speed_x = random.randint(-5, 5) flag_speed_y = random.randint(-5, 5) # 游戏主循环 running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 移动彩旗 flag_x += flag_speed_x flag_y += flag_speed_y # 如果彩旗碰到边界,反转速度方向 if flag_x <= 0 or flag_x + flag_width >= screen_width: flag_speed_x = -flag_speed_x if flag_y <= 0 or flag_y + flag_height >= screen_height: flag_speed_y = -flag_speed_y # 清空屏幕 screen.fill((255, 255, 255)) # 绘制彩旗 screen.blit(flag_image, (flag_x, flag_y)) # 更新屏幕 pygame.display.flip() # 退出游戏 pygame.quit() ``` 请注意,你需要将代码中的"flag.png"替换为你自己的彩旗图片。此外,你还可以根据需要调整彩旗的起始位置、速度等参数。希望这个示例代码能帮助到你!<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [3d max制作彩旗飘飘](https://download.csdn.net/download/m0_71585230/88011500)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [[Rqnoj-371][AHOI1997]彩旗飘飘](https://blog.csdn.net/w745241408/article/details/7176600)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值