[筆記] 圓方樹
阿新 • • 發佈:2022-03-03
仙人掌
與圓方樹的關係
圓方樹最初是用來處理仙人掌問題的,但在處理某些問題時,也可以拓展到一般圖。
定義
每條邊在不超過一個簡單環中的無向圖。
相關問題
如果一個序列問題不夠毒瘤,就上樹,還不夠,就上仙人掌。
不過這裡只考慮一些基礎的問題,一個共同的核心思想就是按照是否在環上來討論。
注意注意程式碼實現中的處理方式。
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]); } }