Distance Queries POJ - 1986 (树上两点的最近公共祖先)

43人阅读 评论(0) 收藏 举报

题目连接:点击打开链接

题意:因为无论如何方向如何,都能建出一棵树。所以方向这个条件可以忽略,问n个点m条边。点和点之间的权值为距离。k次查询,查任意两点的最短距离。

题解:这个一个非常经典的图论问题------LCA。

会用的一种算法:Tarjan---LCA算法。


先明白一个前题:对于有根树T而言的两个节点u,v最近公共祖先LCA(T,u,v)表示一个节点x。满足x是u,v的祖先,且x的深度尽可能大(距离u,v尽可能的近)。对于x点来说,有一点非常特殊,那么就是u到v的路径一定经过x。

这一点是这个算法的核心。明白这个前提了之后。我们再介绍一下算法

这个算法基于深度优先搜索的框架,对于一个新搜到的节点,首先创建由这个节点构成的集合,再对当前节点的每个子树进行搜索,每搜完一颗子树,则可以去欸的那个子树内所有LCA询问都已解决,其他的LCA询问的结果必然在这个子树之外,这时把子树所形成的集合和和当前节点的集合合并,并将当前节点设为集合的祖先。之后继续搜索下一棵子树,直至所有节点的所有子树搜索完。

实现过程:

建立以u为代表元素的集合。

遍历与u相连的节点v,如果没有被访问过,对于v使用Tarjan--LCA算法。结束后,将v的集合合并如u的集合

对于与u有关的询问(u,v)如果v被访问过,则结果就是v所在集合的代表元素。


那么对于这道题。我们不仅要求出来两点的公共子祖先,还有求出距离。那么我们需要开一个dist数组去记录,当前节点到根节点的距离

那么dist【v】 = dist【u】 + (u,v)的权值。

两点的距离为 dist【u】 + dist【v】 - 2*dist【find(u)】;


看代码实现:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;

using namespace std;

const int MAXN = 80080;
const int MAXNQ = 20020;

int father[MAXN];
int Head[MAXN];
int QHead[MAXN];
int Dist[MAXN];

struct EdgeNode{
	int to;
	int next ;
	int lca;
}Edges[MAXN];

EdgeNode QEdges[MAXN];

int find(int x){
	if(x != father[x])
		father[x] = find(father[x]);
	return father[x];
}

bool vis[MAXN];

int LCA(int u){
	father[u] = u;
	vis[u] = true;
	for(int k = Head[u] ; k != -1 ; k = Edges[k].next){
		if(!vis[Edges[k].to]){
			Dist[Edges[k].to] = Dist[u] + Edges[k].lca;
			LCA(Edges[k].to);
			father[Edges[k].to] = u;	
		}
	}
	for(int k = QHead[u] ; k != -1 ;k = QEdges[k].next){
		if(vis[QEdges[k].to]){
			QEdges[k].lca = Dist[u] + Dist[QEdges[k].to] - 2 * Dist[find(QEdges[k].to)];
			QEdges[k^1].lca = QEdges[k].lca;  
		}
	}
}

int main(){
	int N,M,K,u,v,w,a,b;
	char s;
	while(~scanf("%d%d",&N,&M)){
		memset(father,0,sizeof(father));
		memset(Head,-1,sizeof(Head));
		memset(QHead,-1,sizeof(QHead));
		memset(vis,0,sizeof(vis));
		memset(Edges,0,sizeof(Edges));
		memset(QEdges,0,sizeof(QEdges));
		memset(Dist,0,sizeof(Dist));
		int id = 0;
		for(int i = 0 ; i < M ; i ++){
			scanf("%d%d%d %c",&u,&v,&w,&s);
			Edges[id].to = v;
			Edges[id].lca = w;
			Edges[id].next = Head[u];
			Head[u] = id ++;
			Edges[id].to = u;
			Edges[id].lca = w;
			Edges[id].next = Head[v];
			Head[v] = id ++;
		}
		scanf("%d",&K);
		int iq = 0;
		for(int i = 0 ; i < K ; i ++){
			scanf("%d%d",&a,&b);
			QEdges[iq].to = b;
			QEdges[iq].next = QHead[a];
			QHead[a] = iq ++;
			QEdges[iq].to = a;
			QEdges[iq].next = QHead[b];
			QHead[b] = iq ++;
		}
		LCA(1);
		for(int i = 0 ; i < iq ; i += 2)
			printf("%d\n",QEdges[i].lca);
	}
	return 0;
}

查看评论

Thinking football in pattern——通用足球战术体系建模

 Thinking football in pattern——通用足球战术体系建模 摘要:由于目前中国媒体和众多在媒体引导之下的球迷足球评论水平日益进步,阵型相 克理论和整体足球理论(即一个队员要全面...
  • xxcc
  • xxcc
  • 2001-11-28 14:19:00
  • 1291

POJ1986 Distance Queries【最近公共祖先】【Tarjan-LCA算法】

题目大意:John是一个农场主,他的牛很懒,拒绝按照John选的路走。John不得不找一条 最短的路。这道题的输入前半部分和POJ1984"Navigation Nightmare"相同。在每组数据 ...
  • u011676797
  • u011676797
  • 2014-12-31 21:02:06
  • 1710

【POJ 1986】Distance Queries 最近公共祖先

题意:给你一棵树,这棵树上任意边长已知,问你这棵树上任意两个点之间的距离,询问的次数很多,所以每次查询都深搜会超时。思路:以任意结点为根,用LCA的经典算法求出所有查询的两个结点的最近公共祖先,dfs...
  • palqing
  • palqing
  • 2011-04-11 13:52:00
  • 711

poj 1986 Distance Queries(最近公共祖先的tarjan算法)

Distance Queries Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 7626   Accepted:...
  • u010527492
  • u010527492
  • 2013-08-05 13:38:51
  • 807

POJ 1986 Distance Queries(求最近公共祖先,LCA-Tarjan)

Farmer John's cows refused to run in his marathon since he chose a path much too long for their leis...
  • anan15151529
  • anan15151529
  • 2017-08-19 10:08:20
  • 58

POJ 1986 — Distance Queries

原题:http://poj.org/problem?id=1986 题意:有n个点,m条边,下面m行给定一棵树(后面那个字母并没有什么卵用);     Q个询问,求两点间最短距离; 话说...
  • L__emon
  • L__emon
  • 2015-04-21 20:19:50
  • 216

poj 1986 Distance Queries

点击打开链接poj 1986 思路:LCA+Tarjan离线算法+并查集 分析: 1 LCA指的是一棵有根树上两个点的最近公共祖先,或者指的是图上两个点的最短路径。 2 这一题的边...
  • cgl1079743846
  • cgl1079743846
  • 2012-10-09 22:50:34
  • 702

POJ 1986 Distance Queries

题意:求出两个树节点的距离 思路:可以转化成d[u]+d[v]-2*d[lca(u,v)]       d[i]代表根节点到i的距离    lca(u,v)就是u,v的最近公共祖先的意思 模板题 第一...
  • Mr_Xujh
  • Mr_Xujh
  • 2015-08-03 11:33:45
  • 258

POJ 1986——Distance Queries

Description Farmer John's cows refused to run in his marathon since he chose a path much too long f...
  • Guard_Mine
  • Guard_Mine
  • 2014-08-14 19:58:10
  • 358

poj——1986——Distance Queries

Description Farmer John's cows refused to run in his marathon since he chose a path much too long f...
  • u011470356
  • u011470356
  • 2014-03-24 19:46:25
  • 372
    个人资料
    持之以恒
    等级:
    访问量: 7242
    积分: 1497
    排名: 3万+
    文章分类
    最新评论