hdu 6031 Innumerable Ancestors(LCA+剪枝)

题目链接:hdu 6031 Innumerable Ancestors

题意:

给你一棵n个节点的树,现在有m个询问,每次给你两个点集a,b。

让你从a,b点集中选两个点x,y,使得这两个点的LCA的深度最大。

题解:

标解应该是二分+LCA,不过我试了一下暴力,稍微剪了点枝,就直接过去了。

具体看代码

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;i++)
 3 using namespace std;
 4 const int N=1e5+7,DEG=20;
 5 int ed,g[N],nxt[2*N],v[2*N],fa[N][DEG],dep[N];
 6
 7 inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
 8
 9 void dfs(int u,int pre){
10     dep[u]=dep[pre]+1,fa[u][0]=pre;
11     F(i,1,DEG-1)fa[u][i]=fa[fa[u][i-1]][i-1];
12     for(int i=g[u];~i;i=nxt[i])if(v[i]!=pre)dfs(v[i],u);
13 }
14
15 int LCA(int a,int b){
16     if(dep[a]>dep[b])a^=b,b^=a,a^=b;
17     if(dep[a]<dep[b])F(i,0,DEG-1)if((dep[b]-dep[a])&(1<<i))b=fa[b][i];
18     if(a!=b)for(int i=DEG-1;i<0?a=fa[a][0]:0,i>=0;i--)
19     if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
20     return a;
21 }
22
23 int n,m,a[N],b[N];
24
25 bool cmp(const int &a,const int &b)
26 {
27     return dep[a]>dep[b];
28 }
29
30 int main()
31 {
32     while(~scanf("%d%d",&n,&m))
33     {
34         memset(g,-1,sizeof(g));
35         ed=0;
36         F(i,1,n-1)
37         {
38             int x,y;
39             scanf("%d%d",&x,&y);
40             adg(x,y),adg(y,x);
41         }
42         dfs(1,0);
43         F(i,1,m)
44         {
45             int ak,bk;
46             scanf("%d",&ak);
47             F(j,1,ak)scanf("%d",a+j);
48             scanf("%d",&bk);
49             F(j,1,bk)scanf("%d",b+j);
50             sort(a+1,a+1+ak,cmp);
51             sort(b+1,b+1+bk,cmp);
52             int mx=0;
53             F(j,1,ak)
54             {
55                 if(dep[a[j]]<=mx)break;
56                 F(k,1,bk)
57                 {
58                     int lca=LCA(a[j],b[k]);
59                     mx=max(mx,dep[lca]);
60                 }
61             }
62             printf("%d\n",mx);
63         }
64     }
65     return 0;
66 }

时间: 2024-10-26 05:03:14

hdu 6031 Innumerable Ancestors(LCA+剪枝)的相关文章

hdu 6031 Innumerable Ancestors (虚树 lca)

hdu6031 一棵树(根节点是 1),给出两个集合,集合是 由树上的节点组成的.从两个集合中分别选一个元素,求出他们的 lca,问:lca 的深度最大是多少. 每个询问,两个集合,建虚树,然后dfs一遍,记录子树有没有A点.有没有B点,然后看既有A点又有B点的就更新深度到答案. #include <bits/stdc++.h> using namespace std; const int maxN=100000+10; const int maxM=100000+10; const int

HDU 6031 Innumerable Ancestors

树状数组,倍增,枚举,$dfs$序. 对于每一次的询问,可以枚举$B$集合中的所有点,对于每一个点,在树上二分$LCA$,找到最低的更新答案. 判断是否是$LCA$可以搞个$dfs$序,将$A$集合中所有点标$1$,然后查询子树对应的区间上的区间和. #include <bits/stdc++.h> using namespace std; const int maxn = 100010; int L[maxn],R[maxn]; int c[2*maxn]; int h[maxn]; int

HDU6031 Innumerable Ancestors 倍增 - 题意详细概括 - 算法详解

题目 查看原题 - HDU6031 Innumerable Ancestors 题目描述 有一棵有n个节点的有根树,根节点为1,其深度为1,现在有m个询问,每次询问给出两个集合A和B,问LCA(x,y)(x∈A,y∈B)的深度最大为多少. 输入描述 有多组数据(数据组数<=5) 对于每一组数据,首先2个数n,m,表示有根树的节点个数和询问个数.然后n-1行,每行2个数a,b表示节点a和节点b之间存在直接的连边:接下去2m行,每两行,分别描述当前询问的集合A和集合B:对于一个集合,用一行来描述,该

hdu6031 Innumerable Ancestors

hdu6031 Innumerable Ancestors 倍增 题意 给定一张无向图,对于每组询问,给出两个集合 A 与 B 求 lca(x,y) 最深的时候的深度 x属于A y属于B 题解 首先 我们发现答案具有单调性,于是我们就可以二分这个答案 mid 然后 把 a 集合 的 这个深度的祖先 求出来 然后看 与b 集合的这个深度 祖先 是否有交集就行了 用set 判断 是否有交集 用倍增法 快速求出一个点的祖先 求一次 只要 log n 1 #include <bits/stdc++.h>

POJ 1330 Nearest Common Ancestors LCA题解

本题是一个多叉树,然后求两点的最近公共单亲节点. 就是典型的LCA问题.这是一个很多解法的,而且被研究的很透彻的问题. 原始的解法:从根节点往下搜索,若果搜索到两个节点分别在一个节点的两边,那么这个点就是最近公共单亲节点了. Trajan离线算法:首次找到两个节点的时候,如果记录了他们的最低单亲节点,那么答案就是这个最低的单亲节点了. 问题是如何有效记录这个最低单亲节点,并有效根据遍历的情况更新,这就是利用Union Find(并查集)记录已经找到的节点,并及时更新最新访问的节点的当前最低单亲节

POJ 1330 Nearest Common Ancestors LCA(在线RMQ,离线Tarjan)

链接:http://poj.org/problem?id=1330 题意:只看题目就知道题目是什么意思了,最近公共祖先,求在一棵树上两个节点的最近公共祖先. 思路:求最近公共祖先有两种算法,在线和离线,在线方法是用RMQ求LCA,一句话总结就是在从DFS时,从第一个点到第二个点的最短路径中深度最浅的点就是公共祖先,用RMQ处理,一般问题的最优解决方式的复杂度是O(NlogN)的预处理+N*O(1)的查询.离线方法是Tarjan算法,将所有询问的两个点都记录下来,在DFS过程中不断将每个点自身作为

POJ 1470 Closest Common Ancestors LCA题解

本题也是找LCA的题目,不过要求多次查询,一般的暴力查询就必然超时了,故此必须使用更高级的方法,这里使用Tarjan算法. 本题处理Tarjan算法,似乎输入处理也挺麻烦的. 注意: 因为查询的数据会极大,故此使用一个数组记录所有查询数据就会超时的.我就载在这里了.查了好久才想到这点.因为我使用了一个vector容器记录了查询数据,故此每次都循环这组这么大的数据,就超时了.----解决办法:使用一个vector<int> quest来记录查询数组,这样每次都只需要循环某节点的邻接查询点就可以了

HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822 Problem Description Three countries, Red, Yellow, and Blue are in war. The map of battlefield is a tree, which means that there are N nodes and (N – 1) edges that connect all the nodes. Each country

poj 1330 Nearest Common Ancestors lca 在线rmq

Nearest Common Ancestors Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below:  In the figure, each node is labeled with an integer from {1, 2,...,16}. Node 8 is the root of the tree.