牛客网 桂林电子科技大学第三届ACM程序设计竞赛 D.寻找-树上LCA(树上a到b的路径上离c最近的点)
链接:https://ac.nowcoder.com/acm/contest/558/D
来源:牛客网
寻找
输入描述:
第一行一个正整数N,表示节点数量。 接下来N−1行,第i行两个正整数ui,vi,表示第i条边连接节点ui,vi。 接下来一行一个正整数Q,表示询问数量。 接下来Q行,每行三个正整数a,b,c,表示一组询问。
输出描述:
Q行,每行一个正整数,表示每个询问的答案。
备注:
1≤N,Q≤10
5
树上LCA,跑6个lca,然后特殊的a,b都是c的子节点这种情况特判一下就可以了。
代码:
//D
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll; const double PI=acos(-1.0);
const double eps=1e-;
const ll mod=1e9+;
const int inf=0x3f3f3f3f;
const int maxn=1e5+;
const int maxm=+;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int dp[maxn<<][];//数组记得开2倍,因为遍历之后序列长度变为2*n-1
bool vis[maxn];//标记 struct node{
int u,v,w,next;
}edge[maxn<<]; int tot,head[maxn];//head保存的是以当前节点为起点的所有边中最后一条边的编号 int num; inline void add(int u,int v,int w)
{
edge[num].u=u;edge[num].v=v;edge[num].w=w;//存边和权值
edge[num].next=head[u];head[u]=num++;//next保存的是以u为起点的上一条边的编号
u=u^v;v=u^v;u=u^v;//节点互换,存两次,因为为无向图,(u,v)存一次,(v,u)存一次,以下操作同上
edge[num].u=u;edge[num].v=v;edge[num].w=w;
edge[num].next=head[u];head[u]=num++;
} int ver[maxn<<],deep[maxn<<],node[maxn<<],dir[maxn<<];
//ver节点编号,dfs搜索过程中的序列,deep深度,node点编号位置,dir距离 void dfs(int u,int dep)
{
vis[u]=true;//标记u节点被访问过
ver[++tot]=u;//存dfs序
node[u]=tot;//节点的dfs序的编号
deep[tot]=dep;//该编号的深度
for(int k=head[u];k!=-;k=edge[k].next)//倒着遍历以u节点为起点的所有边的编号
if(!vis[edge[k].v]){//如果该编号的边未被访问过
int v=edge[k].v,w=edge[k].w;//v表示该边的终点,w表示该边的权值
dir[v]=dir[u]+w;//权值和
dfs(v,dep+);//再往下dfsv节点的深度
ver[++tot]=u;deep[tot]=dep;//表示dfs的时候还要回溯到上面,就是把dfs序保存一下,走到底再返回去去遍历没走过的点
}
}
//可以看以前写的RMQ(ST)的详解https://www.cnblogs.com/ZERO-/p/8456910.html
void ST(int n)//ST操作
{
for(int i=;i<=n;i++)
dp[i][]=i;//初始化为自己
for(int j=;(<<j)<=n;j++){
for(int i=;i+(<<j)-<=n;i++){
int a=dp[i][j-],b=dp[i+(<<(j-))][j-];
dp[i][j]=deep[a]<deep[b]?a:b;
}
}
} int RMQ(int l,int r)
{
int k=;
while((<<(k+))<=r-l+)k++;//最多能跳2的多少次幂
int a=dp[l][k],b=dp[r-(<<k)+][k];//保存的是编号
return deep[a]<deep[b]?a:b;
} int LCA(int u,int v)
{
int x=node[u],y=node[v];
if(x>y)swap(x,y);
int res=RMQ(x,y);
return ver[res];
} int main()
{
int n,q;
num=;
scanf("%d",&n);
memset(head,-,sizeof(head));//初始化
memset(vis,false,sizeof(vis));
for(int i=;i<n;i++){
int u,v,w;
scanf("%d%d",&u,&v);
w=;
add(u,v,w);//存边
}
tot=;
dir[]=;
dfs(,);
ST(*n-);
cin>>q;
while(q--){
int a,b,c;
int minn=inf,pos;
scanf("%d%d%d",&a,&b,&c);
int A=LCA(a,b);
int B=LCA(a,c);
int C=LCA(b,c);
if(B==C) {
cout<<A<<endl;
continue;
}
int lca=LCA(A,c);
int dis=dir[A]+dir[c]-*dir[lca];
if(minn>dis){
minn=dis;pos=A;
}
lca=LCA(B,c);
dis=dir[B]+dir[c]-*dir[lca];
if(minn>dis){
minn=dis;pos=B;
}
lca=LCA(C,c);
dis=dir[C]+dir[c]-*dir[lca];
if(minn>dis){
minn=dis;pos=C;
}
cout<<pos<<endl;
}
return ;
}
牛客网 桂林电子科技大学第三届ACM程序设计竞赛 D.寻找-树上LCA(树上a到b的路径上离c最近的点)的更多相关文章
- 牛客网 桂林电子科技大学第三届ACM程序设计竞赛 G.路径-带条件的树的直径变形-边权最大,边数偶数的树上的最长路径-树形dp
链接:https://ac.nowcoder.com/acm/contest/558/G 来源:牛客网 路径 小猫在研究树. 小猫在研究路径. 给定一棵N个点的树,每条边有边权,请你求出最长的一条路径 ...
- 牛客网 桂林电子科技大学第三届ACM程序设计竞赛 C.二元-K个二元组最小值和最大-优先队列+贪心(思维)
链接:https://ac.nowcoder.com/acm/contest/558/C来源:牛客网 小猫在研究二元组. 小猫在研究最大值. 给定N个二元组(a1,b1),(a2,b2),…,(aN, ...
- 牛客网 桂林电子科技大学第三届ACM程序设计竞赛 A.串串-后缀自动机模板题
链接:https://ac.nowcoder.com/acm/contest/558/A来源:牛客网 A.串串 小猫在研究字符串. 小猫在研究字串. 给定一个长度为N的字符串S,问所有它的子串Sl…r ...
- 桂林电子科技大学第三届ACM程序设计竞赛 G 路径
链接:https://ac.nowcoder.com/acm/contest/558/G来源:牛客网 小猫在研究树. 小猫在研究路径. 给定一棵N个点的树,每条边有边权,请你求出最长的一条路径,满足经 ...
- 分离 桂林电子科技大学第三届ACM程序设计竞赛
链接:https://ac.nowcoder.com/acm/contest/558/H 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...
- 区间 桂林电子科技大学第三届ACM程序设计竞赛
链接:https://ac.nowcoder.com/acm/contest/558/E 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5242 ...
- 重复 桂林电子科技大学第三届ACM程序设计竞赛
题目链接:https://ac.nowcoder.com/acm/contest/558/B import java.util.HashSet; import java.util.Scanner; p ...
- 相聚 桂林电子科技大学第三届ACM程序设计竞赛
题目链接:https://ac.nowcoder.com/acm/contest/558/D 就是求有多少块区域,用DFS就可以解决,一遇到一个1就从其开始深搜,将其所在的区域块覆灭(变为0),再遇到 ...
- 牛客网 中南林业科技大学第十一届程序设计大赛J题 二分+线段树
https://www.nowcoder.com/acm/contest/124#question 题意 找第一个不小于K的数的下标,然后对它前一个数加一 解析 我们可以维护一个最大值数组 1 ...
随机推荐
- 一道非常易错的js面试题
题目如下: function Foo() { getName = function() { alert(1); }; return this; } Foo.getName = function() { ...
- 判别式模型 vs. 生成式模型
1. 简介 生成式模型(generative model)会对\(x\)和\(y\)的联合分布\(p(x,y)\)进行建模,然后通过贝叶斯公式来求得\(p(y|x)\), 最后选取使得\(p(y|x) ...
- subtle:有趣的伪平铺式窗口管理器
Author:吴吉庆 email: jiqingwu@gmail.com home:http://hi.baidu.com/jiqing0925 create:2011-02-19 update:20 ...
- LintCode 407: Plus One
LintCode 407: Plus One 题目描述 给定一个非负数,表示一个数字数组,在该数的基础上+1,返回一个新的数组. 该数字按照位权大小进行排列,位权最大的数在列表的最前面. 样例 给定 ...
- 【leetcode 简单】 第六十六题 用栈实现队列
使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部. pop() -- 从队列首部移除元素. peek() -- 返回队列首部的元素. empty() -- 返回队列是否为空. ...
- 聊天室(上篇)GatewayWorker 基础
前言 本文的目的是基于 GatewayWorker 官方手册,梳理一次 GatewayWorker,并在实践中与 MVC 框架整合的思路(附最终的项目源码).如果你已经理解了整合这一块儿的知识,那么就 ...
- Microsoft.AspNet.SignalR使用cookie丢失
public void SendGroupMessage(string roomId, string message, string status) { // 调用房间内所有客户端的sendMessa ...
- 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 Coin 概率+矩阵快速幂
题目链接: https://nanti.jisuanke.com/t/17115 题意: 询问硬币K次,正面朝上次数为偶数. 思路: dp[i][0] = 下* dp[i-1][0] + 上*dp[i ...
- Django-模板语言和过滤器
Django模板语言 首先模板只是一个文本文件,它可以生成任何基于文本的格式(HTML.XML.CSS等),模板中包含变量,在模板被渲染的时候替换为最终的值,以及控制模板逻辑的标签. 变量使用{{ 变 ...
- Flask:文件配置方式实践及其中的各种问题记录
Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2, 提示: 1.请查看本文后面的“18-07-17 11:18重大纠正” ! 2.flask run命令运行时传入参数 ...