1. 程式人生 > >【洛谷】3379 【模板】最近公共祖先(LCA)

【洛谷】3379 【模板】最近公共祖先(LCA)

題目傳送門

誒,自己真的是越來越菜了,自己寒假裡學會的LCA到現在已經忘得差不多了。

今天就當是複習一下吧。

其實這個倍增的思想還是挺神奇的,每次詢問時先把深度較大的節點倍增到和深度較小的節點同一深度。

然後再把這兩個節點同時倍增到離它們最遠的不相同的祖先出,賦值並迴圈,最後返回當前任意一個節點的父親節點就是這兩個節點的LCA了。

附上AC程式碼:

#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
#define N 500010
using namespace std;

struct side{
	int to,nt;
}s[N<<1];
int n,m,st,x,y,num,h[N],d[N],f[N][21],k;
bool b[N];

inline char nc(){
	static char ch[100010],*p1=ch,*p2=ch;
	return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &a){
	static char c=nc();int f=1;
	for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
	for (a=0;isdigit(c);a=a*10+c-'0',c=nc());
	a*=f;return; 
}

inline void add(int x,int y){
	s[++num]=(side){y,h[x]},h[x]=num;
	s[++num]=(side){x,h[y]},h[y]=num;
}

inline void build(int x){
	b[x]=1;
	for (int i=h[x]; i; i=s[i].nt)
		if (!b[s[i].to])
			d[s[i].to]=d[x]+1,f[s[i].to][0]=x,build(s[i].to);
	return;
}

inline int query(int x,int y){
	if (d[x]<d[y]) swap(x,y);
	for (int i=k; i>=0; --i)
		if (d[f[x][i]]>=d[y]) x=f[x][i];
	if (x==y) return x;
	for (int i=k; i>=0; --i)
		if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
	return f[x][0];
}

int main(void){
	read(n),read(m),read(st);
	for (int i=1; i<n; ++i) read(x),read(y),add(x,y);
	d[st]=1,build(st),k=log(n)/log(2)+1;
	for (int j=1; j<=k; ++j)
		for (int i=1; i<=n; ++i)
			f[i][j]=f[f[i][j-1]][j-1];
	for (int i=1; i<=m; ++i){
		read(x),read(y);
		printf("%d\n",query(x,y));
	}
	return 0;
}

相關推薦

3379 模板最近公共祖先LCA

題目傳送門 誒,自己真的是越來越菜了,自己寒假裡學會的LCA到現在已經忘得差不多了。 今天就當是複習一下吧。 其實這個倍增的思想還是挺神奇的,每次詢問時先把深度較大的節點倍增到和深度較小的節點同一深度。 然後再把這兩個節點同時倍增到離它們最遠的不相同的祖先出,賦值並迴圈,最

模板·LCA3379 最近公共祖先LCA

思路:tarjan。 程式碼: #include <cstdio> #include <iostream> #include <algorithm>

3379 模板最近公共祖先LCA 樹上倍增+LCA

題目 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。 題解 樹上倍增和普通的倍增原理是一樣的,它的運用很廣泛,除了求LCA外,在很多問題中都有應用 倍增就是將狀態空間中2的整數次冪的值作為代表,當要查詢其它位置的值時,可以通過“任意整數可

P3379 模板最近公共祖先LCA

tchar tarjan == splay tar ins mes class display 洛谷P3379 【模板】最近公共祖先(LCA) 題目描述 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。 輸入輸出格式 輸入格式: 第一行包含三個正整數

P3379 模板最近公共祖先LCA 如題

content 接下來 mit 裏的 mar lap define 第一次 樹根 P3379 【模板】最近公共祖先(LCA) 時空限制1s / 512MB 題目描述 如題,給定一棵有根多叉樹,請求出指定兩個點直接

P3379 模板最近公共祖先LCA樹鏈剖分

樹鏈剖分 turn 規模 一次 .org pen 整數 src namespace 題目描述 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。 輸入輸出格式 輸入格式: 第一行包含三個正整數N、M、S,分別表示樹的結點個數、詢問的個數和樹根結點的

P3379 模板最近公共祖先LCA

span IT HR pre define 結點 using for 公共祖先 P3379 【模板】最近公共祖先(LCA) 題目描述 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。 輸入輸出格式 輸入格式: 第

P3379 模板最近公共祖先LCA (線上倍增+離線Tarjan)

題目描述 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。 輸入格式: 第一行包含三個正整數N、M、S,分別表示樹的結點個數、詢問的個數和樹根結點的序號。

luogu_3379 模板最近公共祖先LCA

span oid ont return mes ace print next using #include<bits/stdc++.h>using namespace std;#define N 500010*2struct edge{int v,next;}

P3379 模板最近公共祖先LCAdfs序

log 輸出格式 sample namespace i++ 技術分享 規模 link wap P3379 【模板】最近公共祖先(LCA) 題目描述 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。 輸入輸出格式 輸入格式: 第一行包含三個正整數

C++ P3379 模板最近公共祖先LCA

早就想寫LCA了,奈何沒有dfs基礎,先做了最小生成樹 廢話就說到這裡,上程式碼。 #include<cstdio> #include<iostream> #include<algorithm> #include<cstri

P3379 模板最近公共祖先LCALCT

\(\color{#0066ff}{ 題目描述 }\) 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。 \(\color{#0066ff}{輸入格式}\) 第一行包含三個正整數N、M、S,分別表示樹的結點個數、詢問的個數和樹根結點的序號。 接下來N-1行每行包含兩個正整數x、y,表示x

Luogu P3379 模板最近公共祖先LCA

col tdi www pac div 祖先 http https 最近公共祖先 qwq 懶得寫了明天補 為啥不開兩倍會re啊 代碼 #include<cstdio> #include<iostream> #include<cmath>

模板最近公共祖先LCA

href ret tar long long c++ amp 心算 class not 題目鏈接:https://www.luogu.org/problemnew/show/P3379 #include <bits/stdc++.h> using nam

最近公共祖先LCA 倍增演算法

題目連結:洛谷-P3379 ## **題目描述**: 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。 思路 這是一個裸的LCA問題,即求書上兩個節點的最近公共祖先。 我們可以用樹上倍增來做; 當然,在做之前我們假設不知道該演算法。那麼我們如何來做

lcaP3379 最近公共祖先LCA

int arc pragma rpi == 代碼 輸出 () div 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先. 輸入格式: 第一行包含三個正整數N、M、S,分別表示樹的結點個數、詢問的個數和樹根結點的序號。 接下來N-1行每行包含兩個正整數x、y

P2858·動態規劃[USACO06FEB]奶牛零食Treats for the Cows

greate single nes 得到 form images include 規劃 ive 題面 題目描述 FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money

mNOIP模擬賽Day1T1 斐波那契

lld -s ace can using code 我們 namespace log 題目傳送門:https://www.luogu.org/problemnew/show/P3938 這題出得特別吼啊~~ 通過打表或者大膽猜想斐波那契數列的一些性質,我們不難發現對於一

九月月賽T1簽到題bsgs快速乘

code 是我 好的 取模 lin pri sca ast for 說好的簽到題呢qwq。。。。怎麽我簽到題都不會啊qwq 之後看了bsgs才發現貌似不是那麽那麽難fake!!什麽東西。。。 先貼上部分分做法(也就是枚舉1的個數,然後每一步都進行取模(這和最後取模結果一樣,

P3038 [USACO11DEC]牧草種植樹鏈剖分邊權修改與查詢

【連結】 https://www.luogu.org/problemnew/show/P3038 【題意】 給出一棵n個節點的樹,有m個操作,操作為將一條路徑上的邊權加一或詢問某條邊的權值。 【思路】 樹鏈剖分的裸題。 但是這個題是在邊上進行操作,我們考慮把邊上的操作轉移到點