【模版】广义圆方树

一、建树:

==> 推倒重建版:
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子节点权值集合

posted on 2024-11-10 22:54  Ueesugi_sakura  阅读(1)  评论(0编辑  收藏  举报