parent[i][j]:表示節點u的第2^j個祖先
dis[i]:dfs時間戳,即節點到根節點距離,即深度
const int pow = 18;
const int maxn=5e5+10;
int parent[maxn][pow+10];//parent[i][j]表示節點u的第2^j個祖先
vectoredge[maxn];
int dis[maxn];//dfs時間戳,即節點到根節點距離,即深度
void dfs(int u,int fa)
return a;
}
theme:求三個人位於不同的三個節點,求它們集合與一點共需花費的最少步數與點的編號。1<=n,m<=5*10^5
solution:設a,b,c兩兩的最近公共祖先分別為ab,ac,bc,三個點的最近公共祖先為與其它兩個不同的。則我們求出ab,ac,bc後判斷它們的相等關係即可,而所需距離由dis相減即可。
//三個點的最近公共祖先
#includeusing namespace std;
const int maxn=5e5+10;
const int pow = 18;
int parent[maxn][pow+10];//parent[i][j]表示節點u的第2^j個祖先
vectoredge[maxn];
int dis[maxn];
void dfs(int u,int fa)
return a;
}int main()
dfs(1,0);
for(int i=1;i<=m;++i)
else if(ab==ac)
else if(bc==ac)
}}
theme:給定一棵樹,n個節點,m此詢問,每次詢問與節點u為p級兄弟的個數,p級兄弟即a,b有公共的p級祖先。(1 ≤ n,m ≤ 10^5)
solution:首先通過lca演算法算出parent[i][j],在深蒐時記錄下進入每個節點的時間戳與離開該節點的時間戳,將每個深度的節點的時間戳用乙個vector記錄。則每次詢問時,先通過parent找到u的p祖先pa,再通過lower_bound()二分找出大於pa進入時間戳的個數與離開時間戳的個數,相減即可。
//找u的p級兄弟
#includeusing namespace std;
const int maxn=1e5+10;
const int pow = 18;
int parent[maxn][pow+10];//parent[i][j]表示節點u的第2^j個祖先
vectoredge[maxn];
vectordeep[maxn];
int dis[maxn];
int in[maxn],out[maxn];
int cnt,maxdept=0;
void dfs(int u,int fa)
return now;
}int main()
dfs(0,0);
for(int i=1;i<=maxdept;++i)
sort(deep[i].begin(),deep[i].end());
cin>>m;
for(int i=1;i<=m;++i)
}}
求LCA(最近公共祖先)
演算法1 樹上倍增 hdu 2586 include include include define maxn 40000 5 define inf 999999999 using namespace std int n,m,t,q,head maxn x,y,z,vis maxn fa maxn c...
LCA 求最近公共祖先
洛谷3379 基本思路 要求兩個點的最近公共祖先,首先我們用乙個陣列fa x i 來表示節點x的向上2 i層的祖先編號,先dfs求出每個點的深度和預處理fa陣列。再求兩個節點的最近公共祖先時,先讓深度大的跳到相同的一層,再嘗試以log2 depth x 的跨度跳至祖先節點,相同時不跳 因為可能不是最...
最近公共祖先 LCA 最近公共祖先
直接暴力搜尋參考 普通搜尋每次查詢都需要 樸素演算法是一層一層往上找,倍增的話直接預處理出乙個 具體做法是 維護乙個 的關係來線性求出這個陣列 int anc n 31 int dep n 記錄節點深度 void dfs int u,int parent for int i 0 i g u size...