給出乙個樹和m
m組詢問,對於每個詢問輸出兩個結點的lca
lca。
##思路:
思路一:樹上倍增
樹上倍增是lca
lca的基本方法之一。其做法是先將xx和y
y跳到統一深度上,再利用倍增思想找到兩點的lca
lca。
所以要先用dfs
dfs求出每個點的深度以及它的祖宗,然後在對於每一詢問完成上述操作即可。
思路二:sts
t表對於一棵樹上的兩個不同節點xx和y
y,從根開始跑一遍尤拉序,設x
x在尤拉序中第一次出現的位置為fir
st[x
]fir
st[x
],yy第一出現的位置是fir
st[y
]fir
st[y
],那麼xx和y
y的lca
lca就是尤拉序中fir
st[x
]fir
st[x
]到fir
st[y
]fir
st[y
]之間深度最低的(即min
(dep
[i])
min(
dep[
i]))節點就是它們的lca
lca。
證明略。但是很明顯是正確的。
所以,先跑一邊dfs
dfs求出fir
st[i
]fir
st[i
]和尤拉序,再利用sts
t表求出任意區間的最小值(lca
lca),然後再讀入輸出即可。
注意!此方法時間較慢,需要輸入輸出流才能過!
##**:
樹上倍增:
#include #include #include #include #define n 500030
#define lg 25
using namespace std;
int dep[n+1],head[n+1],lg[lg+1],k,n,m,s,x,y,f[n+1][lg+1];
struct edge //鄰接表
e[n<<1+1];
void add(int from,int to)
void dfs(int x,int fa) //求每個點的深度
return f[x][0];
}int main()
return 0;
}
sts
t表:
#include #include #include #include #define n 500020
#define lg 20
using namespace std;
int first[n<<1+1],dep[n<<1+1],vis[n<<1+1],rmq[n<<1+1][lg],num[n<<1+1][lg],head[n<<1/+1];
int n,m,s,k,sum,x,y,z;
struct edge
e[n<<1+1];
int f;
char c;
int read() //輸入流
void write(int x) //輸出流(可以不用)
void add(int from,int to)
void dfs(int x,int k) //求尤拉序
return;
}int main()
getchar();getchar();
return 0;
}
模板 最近公共祖先(LCA)
題自洛谷 如題,給定一棵有根多叉樹,請求出指定兩個點直接最近的公共祖先。輸入格式 第一行包含三個正整數n m s,分別表示樹的結點個數 詢問的個數和樹根結點的序號。接下來n 1行每行包含兩個正整數x y,表示x結點和y結點之間有一條直接連線的邊 資料保證可以構成樹 接下來m行每行包含兩個正整數a b...
模板 lca 最近公共祖先
lca hljs cpp include include using namespace std const int maxn 500001 int n,m,gen,x,y struct edgeedge 2 maxn int deep maxn fa maxn 20 deep記錄每個點的深度,fa...
最近公共祖先 LCA 模板
lca即最近公共祖先,是指 在有根樹中,找出某兩個結點u和v最近的公共祖先。時間複雜度o nlogn m n 步驟 1.將樹看作乙個無向圖,從根節點開始深搜,得到乙個遍歷序列。2.在x y區間中利用rmq演算法找到深度最小返回其下標。可以上洛谷找模板題測試 include include inclu...