1. 程式人生 > 其它 >[筆記] 圓方樹

[筆記] 圓方樹

仙人掌

與圓方樹的關係

圓方樹最初是用來處理仙人掌問題的,但在處理某些問題時,也可以拓展到一般圖。

定義

每條邊在不超過一個簡單環中的無向圖。

相關問題

如果一個序列問題不夠毒瘤,就上樹,還不夠,就上仙人掌。

不過這裡只考慮一些基礎的問題,一個共同的核心思想就是按照是否在環上來討論。

注意注意程式碼實現中的處理方式。

void solve(int x, int y){
	int len = dep[y] - dep[x] + 1;// 環的長度
	/* do some thing */
}
void tarjan(int x){
	dfn[x] = low[x] = ++tim; 
	for(int i = head[x]; i; i = e[i].nx){
		int y = e[i].to; if(y == fa[x]) continue;
		if(!dfn[y]){
			fa[y] = x, dep[y] = dep[x] + 1;
			tarjan(y), low[x] = min(low[x], low[y]);
			if(low[y] > dfn[x]) /* 按照樹邊處理 */;
		}else low[x] = min(low[x], dfn[y]);
	}
	for(int i = head[x]; i; i = e[i].nx){
		int y = e[i].to;/* x 是環上最淺的點,y 是最深的點 */	
		if(fa[y] != x && dfn[y] > dfn[x]) solve(x, y);
	}
}

ex仙人掌相關問題的處理方法 by zhangche0526

圓方樹的構建

對於每個點雙,建立一個方點,與點雙內的點連邊。

void tarjan(int x){
	dfn[x] = low[x] = ++tim, stk[++top] = x;
	for(int i = head[x]; i; i = e[i].nx){
		int y = e[i].to;
		if(!dfn[y]){
			tarjan(y), low[x] = min(low[x], low[y]);
			if(low[y] >= dfn[x]){
				++tot, Add(tot, x);
				while(stk[top + 1] != y) Add(tot, stk[top]), --top;
			}
		}else low[x] = min(low[x], dfn[y]);
	}
}