1. 程式人生 > >2586 How far away ? (LCA求樹上兩點間距離模板題)

2586 How far away ? (LCA求樹上兩點間距離模板題)

There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.

Input

First line is a single integer T(T<=10), indicating the number of test cases.
  For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
  Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.

Output

For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.

Sample Input

2
3 2
1 2 10
3 1 15
1 2
2 3

2 2
1 2 100
1 2
2 1

Sample Output

10
25
100
100

題解:

首先要知道:樹上任意兩點A,B之間的距離 = 根節點到A的距離 + 根節點到B的距離 - 2*根節點到AB最近公共祖先節點的距離。

然後只要求LCA就行了。

Tarjan離線版程式碼:

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 40005; 
 
pair<int,int> P[205];//存詢問邊
int lca[205];//存詢問邊對應的最近公共祖先 

struct Edge{//存樹邊 
	int to,next,w;//w為邊權 
}E[MAXN*2];

int head[MAXN],tot;

inline void Add(int from,int to,int w){
	E[++tot].next = head[from];
	E[tot].to = to;
	E[tot].w = w;
	head[from] = tot;
	E[++tot].next = head[to];
	E[tot].to = from;
	E[tot].w = w;
	head[to] = tot;
}

struct Query{//存每個點對應的詢問邊
	int to,next,id;
}Q[405];

int headQ[MAXN],totq;

inline void AddQ(int from,int to,int id){ 
	Q[++totq].next = headQ[from];
	Q[totq].to = to;
	Q[totq].id = id;
	headQ[from] = totq;
	Q[++totq].next = headQ[to];
	Q[totq].to = from;
	Q[totq].id = id;
	headQ[to] = totq;
} 

int dis[MAXN];//記錄根節點到每個點的距離 
bool vis[MAXN];
int fa[MAXN];//並查集祖先陣列 

int Find(int x){
	if(fa[x] == x)return x;
	return fa[x] = Find(fa[x]);
}

void Union(int a,int b){
	int A = Find(a);
	int B = Find(b);
	if(A != B)fa[B] = A;
}

void Tarjan(int rt){
	vis[rt] = true;
	int to;
	for(int i=head[rt] ; i ; i=E[i].next){
		to = E[i].to;
		if(!vis[to]){
			dis[to] = dis[rt] + E[i].w;
			Tarjan(to);
			Union(rt,to);
		}
	}
	for(int i=headQ[rt] ; i ; i=Q[i].next){
		to = Q[i].to;
		if(vis[to]){
			lca[Q[i].id] = Find(to);
		}
	}
}

inline void init(int n){
	for(int i=0 ; i<=n ; ++i)fa[i] = i;
	memset(vis,false,sizeof vis);
	memset(head,0,sizeof head);
	memset(headQ,0,sizeof headQ);
	tot = totq = 0;
}

int main(){
		
	int T,n,m;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&m);
		init(n);
		int a,b,c;
		for(int i=1 ; i<n ; ++i){
			scanf("%d %d %d",&a,&b,&c);
			Add(a,b,c);
		}
		for(int i=1 ; i<=m ; ++i){
			scanf("%d %d",&P[i].first,&P[i].second);
			AddQ(P[i].first,P[i].second,i);
		}
		dis[1] = 0;//這裡選的根節點為 1 
		Tarjan(1);
		for(int i=1 ; i<=m ; ++i){
			printf("%d\n",dis[P[i].first]+dis[P[i].second]-2*dis[lca[i]]); 
		}
	}
	
	return 0;
}

相關推薦

2586 How far away ? (LCA樹上兩點距離模板

There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is i

HDU 2586 How far away ?(LCA Tarjan/樹上倍增

題目:問任意兩個點之間的最短路徑長。 如果用Tarjan做的話,那麼 用LCA算出最近公共祖先lca,長度就是dis[u]+dis[v]-2*dis[lca] #include<iostream> #include<cstdio> #incl

HDU 2586 How far away ?(LCA模板 近期公共祖先啊

sizeof rmq round pad show mod 部分 cas sam 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n hou

HDU 2586 How far away ?(LCA在線算法實現

計算 algo size vector tar urn target nbsp struct http://acm.hdu.edu.cn/showproblem.php?pid=2586 題意:給出一棵樹,求出樹上任意兩點之間的距離。 思路: 這道題可以利用LC

hdu 2586 How far away ? 離線LCA

相加 ref 雙向 std pid edge markdown syn down 題目鏈接:hadu 2586 題目大意: 城鎮之間互相有道路(雙向邊),且只存在n-1條邊,保證相互可達,求兩點 之間的距離。 思路: 轉化為LCA裸問題,只需要再一邊尋找最近公共祖先的

hdu 2586 How far away ?倍增LCA

printf truct != algorithm for sin can -i cnblogs hdu 2586 How far away ?倍增LCA 題目鏈接 http://acm.hdu.edu.cn/showproblem.php?pid=2586 思路: 針對

HDU - 2586 How far away? 在線LCA ST算法

ole poi cto st算法 求解 style after nsis return There are n houses in the village and some bidirectional roads connecting them. Every day peo

hdu 2586 How far away?(LCA模板+離線tarjan演算法

How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 25408 &nbs

HDU 2586 How far away?(LCA使用詳解

There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go

hdu 2586 How far away

unique time first turn chm rom memset def nsis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S

HDU-2586 How far away

ota for each length name amp pac simple return 解題思路 How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K

hdu——2586 How far away

ostream style ask read sea sim bottom following ems How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K

HDU - 2586 How far away

cti blog ever simple nes printf const you print There are n houses in the village and some bidirectional roads connecting them. Every day

F. Drivers Dissatisfaction+最小生成樹+lca樹上兩點的最大值

continue tmp rst spa 題解 去掉 題意 drive .com 題目鏈接:F. Drivers Dissatisfaction 題意:n個點,m條邊,每條邊有一個w,代表這條路的不滿意度,每一條邊我們可以花費c來使不滿意讀-1;然後問你有s,找到一棵生成

2586. How far away ?(HDU

題意理解 一個村莊有很多戶人家,任意兩戶人家最多有一條路相連。已知每條路相連的兩戶人家的編號和長度,求從A戶人家到B戶人家有多遠? 問題分析 LCA+RMQ資料結構,最近公共祖先+區間最小值 轉1:首先用圖表示村莊的連線情況。使用鄰接表儲存,使用heads陣列存節點資訊,使用edge

POJ 4718 /// 樹鏈剖分+線段樹區間合併 樹上兩點的LCIS長度

題目大意: 給定n個點 每個點都有權值 接下來給定樹的n條邊 第 i 個數 a[i] 表示 i+1到a[i]之間 有一條邊 給定q q個詢問 每次詢問給出 x y 求x到y的最長上升子序列的長度   題解 https://blog.csdn.net/forever_wjs/article/

POJ 4718 /// 樹鏈剖分+線段樹區間合並 樹上兩點的LCIS長度

一次 tree 部分 i+1 clu 給定 top namespace oid 題目大意: 給定n個點 每個點都有權值 接下來給定樹的n條邊 第 i 個數 a[i] 表示 i+1到a[i]之間 有一條邊 給定q q個詢問 每次詢問給出 x y 求x到y的最長上升子序列的長度

任意多邊形面積(模板

題目描述 眾所周知的是,小X特別喜歡由線條組成的形狀,比如說凸多邊形,這一天小X正在紙上畫著喜歡的凸多邊形,這時候小Y走了過來,指著一張圖片上的多邊形,問小X知道這個圖形的面積麼,這可把小X難住了,聰明的你一定能夠幫助小X解決這個問題,對吧~ 輸入描述: 多邊形上最多有

How far away ? HDU - 2586(LCA Tarjan離線方法 or 倍增線上方法)

How far away ? HDU - 2586 題目連結 題意:給出一棵樹,問任意兩點的間的最小距離; 思路:考慮本題,若t時a, b的LCA,r是樹根那麼dis[a, b]=dis[r, a]+dis[r, b]-2*dis[r, t]; dis[r, p] (根到p點

HDU How far away ?--LCA

while nts 分享 put numbers ont integer simple people Problem Description There are n houses in the village and some bidirectional roads co