【模版】广义圆方树
一、建树:
==> 推倒重建版:
void tarjan(int u, int father) {
stack[++top] = v;
dfn[u] = low[u] = ++num;
for(int i = head[u]; i; i = ed[i].last)
{
int v = ed[i].to;
if(v == father) continue;
if(!dfn[v])
{
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] >= low[u]) //求点双连通分量
{
int tmp; ++cnt;
do {
tmp = stack[top--];
belong[tmp].push_back(cnt);
} while(tmp != v);
belong[u].push_back(cnt);
}
}
else low[u] = min(low[u], dfn[v]);
}
}
void rebuild() {
G.init();// 猜测是把G记录的原图清理干净
for(int i = 1; i <= n; i ++)
{
for(int j = 0; j < (int)belong[i].size(); j ++)
{
G.insert({i, belong[i][j]});
}
}
}
==> 边扫边建版:
void tarjan(int u, int father) {
stack[++top] = v;
dfn[u] = low[u] = ++num;
for(int i = head[u]; i; i = ed[i].last)
{
int v = ed[i].to;
if(v == father) continue;
if(!dfn[v])
{
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] >= low[u]) //求点双连通分量
{
++cnt;// 猜测cnt的初值为n
lk(cnt, u); lk(u, cnt);
int tmp;
do {
tmp = stack[top--];
lk(cnt, tmp); lk(tmp, cnt);
} while(tmp != v);
}
}
else low[u] = min(low[u], dfn[v]);
}
}
二、应用:
1.统计简单路径 ———— 修改“圆点”权值 + 访问两点间路径中的Max和Min
==> data structure : 线段树 + 树链剖分 + multiset维护fa子节点权值集合