POJ 1986 Distance Queries LCA两点距离树

标题来源:POJ 1986 Distance Queries

意甲冠军:给你一棵树 q第二次查询 每次你问两个点之间的距离

思路:对于2点 u v dis(u,v) = dis(root,u) + dis(root,v) - 2*dis(roor,LCA(u,v)) 求近期公共祖先和dis数组

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 40010;
int first[maxn], head[maxn], cnt, sum;
struct edge
{
	int u, v, w, next;
}e[maxn*2], qe[maxn], Q[maxn];
int ans[maxn];
int f[maxn], vis[maxn];
int d[maxn];
void AddEdge(int u, int v, int w)
{
	e[cnt].u = u;
	e[cnt].v = v;
	e[cnt].w = w;
	e[cnt].next = first[u];
	first[u] = cnt++;
	e[cnt].u = v;
	e[cnt].v = u;
	e[cnt].w = w;
	e[cnt].next = first[v];
	first[v] = cnt++;
}

void AddEdge2(int u, int v, int w)
{
	qe[sum].u = u;
	qe[sum].v = v;
	qe[sum].w = w;
	qe[sum].next = head[u];
	head[u] = sum++;
	qe[sum].u = v;
	qe[sum].v = u;
	qe[sum].w = w;
	qe[sum].next = head[v];
	head[v] = sum++;
}

int find(int x)
{
	if(f[x] != x)
		return f[x] = find(f[x]);
	return f[x];
}
void LCA(int u, int k)
{
	f[u] = u;
	d[u] = k;
	vis[u] = true;
	for(int i = first[u]; i != -1; i = e[i].next)
	{
		int v = e[i].v;
		if(vis[v])
			continue;
		LCA(v, k + e[i].w);
		f[v] = u;
	}
	for(int i = head[u]; i != -1; i = qe[i].next)
	{
		int v = qe[i].v;
		if(vis[v])
		{
			ans[qe[i].w] = find(v);
		}
	}
}
int main()
{
	int n, m;
	memset(first, -1, sizeof(first));
	memset(head, -1, sizeof(head));
	cnt = 0;
	sum = 0;
	scanf("%d %d", &n, &m);
	for(int i = 0; i < m; i++)
	{
		int u, v, w;
		char s[10];
		scanf("%d %d %d %s", &u, &v, &w, s);
		AddEdge(u, v, w);
	}
	int q;
	scanf("%d", &q);
	for(int i = 0; i < q; i++)
	{
		int u, v;
		scanf("%d %d", &u, &v);
		Q[i].u = u, Q[i].v = v;
		AddEdge2(u, v, i);
		AddEdge2(v, u, i);

	}
	memset(vis, 0, sizeof(vis));
	d[1] = 0;
	LCA(1, 0);
	for(int i = 0; i < q; i++)
	{
		int u = Q[i].u, v = Q[i].v;
		printf("%d\n", d[u] + d[v] - 2*d[ans[i]]);
	}
	return 0;
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

时间: 2024-10-10 23:02:20

POJ 1986 Distance Queries LCA两点距离树的相关文章

POJ 1986 Distance Queries LCA树上两点的距离

题目来源:POJ 1986 Distance Queries 题意:给你一颗树 q次询问 每次询问你两点之间的距离 思路:对于2点 u v dis(u,v) = dis(root,u) + dis(root,v) - 2*dis(roor,LCA(u,v)) 求最近公共祖先和dis数组 #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn =

poj 1986 Distance Queries LCA

题目链接:http://poj.org/problem?id=1986 Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifestyle. He therefore wants to find a path of a more reasonable length. The input to this problem consists

POJ 1986 Distance Queries 【输入YY &amp;&amp; LCA(Tarjan离线)】

任意门:http://poj.org/problem?id=1986 Distance Queries Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 16648   Accepted: 5817 Case Time Limit: 1000MS Description Farmer John's cows refused to run in his marathon since he chose a path much t

poj 1986 Distance Queries 带权lca 模版题

Distance Queries Description Farmer John's cows refused to run in his marathon since he chose a path much too long for their leisurely lifestyle. He therefore wants to find a path of a more reasonable length. The input to this problem consists of the

POJ 1986 Distance Queries (在线LCA转RMQ)

题目地址:POJ 1986 纯模板题.输入的最后一个字母是多余的,完全不用管.还有注意询问的时候有相同点的情况. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set>

POJ 1986 Distance Queries(LCA)

[题目链接] http://poj.org/problem?id=1986 [题目大意] 给出一棵树,问任意两点间距离. [题解] u,v之间距离为dis[u]+dis[v]-2*dis[LCA(u,v)] [代码] #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=300010; int d[N],num[N],dis[N],ed=0,x

POJ 1986 Distance Queries

http://poj.org/problem?id=1986 题意:一棵树里找到两个点的距离.(不用考虑不联通的情况) 题解:LCA模板题. 1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <string> 5 #include <cstdio> 6 #include <cmath> 7 #include <queue>

POJ - 1986 Distance Queries(离线Tarjan算法)

1.一颗树中,给出a,b,求最近的距离.(我没考虑不联通的情况,即不是一颗树的情况) 2.用最近公共祖先来求, 记下根结点到任意一点的距离dis[],这样ans = dis[u] + dis[v] - 2 * dis[lca(u, v)] 3. /* 离线算法,LCATarjan 复杂度O(n+Q); */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; const

POJ 1986 DIstance Query LCA水题

给出一棵树,对于每一个询问,给出2个节点,输出2个节点的距离. 输入中有字母,那个是没有用的,不用管. 思路: 0.选择编号为1的节点作为树的root (注意:有些题的边是单向的,这时候我们要根据节点的入度来确定root, 双向的话一般可以随意选择一个节点作为root) 1.dfs1,求出dep和pa[i][0] 2.初始化数组pa 3.节点(u,v)的权值为w 把本来是边的权值w赋给u,v中dep较大的节点, cost[i]表示节点i的权值为cost[i] 先初始化:cost[root]=0