Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
lca_edge.hpp
[詳解]
1#include "../../../kyopro_library/template.hpp"
2
3/// @brief 辺属性LCA
4template<typename Monoid>
5struct LcaEdge {
6 using Type=typename Monoid::Type;
7
8 /// @brief コンストラクタ
9 /// @param g 重み付き木
10 LcaEdge(const vector<vector<pair<int,Type>>>& g, int root=0) {
11 int n=g.size();
12 int k=1;
13 while((1<<k)<n) k++;
14 par=vector<vector<int>>(k,vector<int>(n,-1)),dep=vector<int>(n),dat=vector<vector<Type>>(k,vector<Type>(n,Monoid::id()));
15 dfs(g,root,-1);
16 for(int i=0; i<k-1; i++) for(int j=0; j<n; j++) {
17 par[i+1][j]=par[i][j]==-1?-1:par[i][par[i][j]];
18 dat[i+1][j]=par[i][j]==-1?Monoid::id():Monoid::op(dat[i][j],dat[i][par[i][j]]);
19 }
20 }
21
22 /// @brief パス u-v のモノイド積を返す
23 Type fold(int u, int v) {
24 if(dep[u]>dep[v]) swap(u,v);
25 Type ret=Monoid::id();
26 while(dep[u]<dep[v]) {
27 int k=0;
28 while((dep[v]-dep[u])>=(1<<(k+1))) k++;
29 ret=Monoid::op(ret,dat[k][v]),v=par[k][v];
30 }
31 while(u!=v) {
32 int k=0;
33 while(par[k+1][u]!=par[k+1][v]) k++;
34 ret=Monoid::op(ret,dat[k][u]),ret=Monoid::op(ret,dat[k][v]);
35 u=par[k][u],v=par[k][v];
36 }
37 return ret;
38 }
39
40private:
41 vector<vector<int>> par;
42 vector<int> dep;
43 vector<vector<Type>> dat;
44 void dfs(const vector<vector<pair<int,Type>>>& g, int now, int pre) {
45 par[0][now]=pre; dep[now]=(pre==-1 ? 0 : dep[pre]+1);
46 for(auto [nxt,cost]: g[now]) {
47 if(nxt==pre) continue;
48 dat[0][nxt]=cost;
49 dfs(g,nxt,now);
50 }
51 }
52};
53
54#include"../../../kyopro_library/others/monoid.hpp"
辺属性LCA
Definition lca_edge.hpp:5
LcaEdge(const vector< vector< pair< int, Type > > > &g, int root=0)
コンストラクタ
Definition lca_edge.hpp:10
Type fold(int u, int v)
パス u-v のモノイド積を返す
Definition lca_edge.hpp:23