日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[学习笔记]圆方树广义圆方树

發布時間:2025/3/21 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [学习笔记]圆方树广义圆方树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引入

偶爾,我們會遇到一些要在無向圖/仙人掌上做的問題,這些問題如果在樹上就會比較方便,那么我們就開始考慮能不能把原圖等效成一棵樹,然后就可以方便地亂搞了?

圓方樹就是一種將無向圖/仙人掌變成樹的數據結構

一般無向圖的圓方樹

構建

對于一般的無向圖,不滿足樹形結構的部分無非是邊雙聯通分量、點雙聯通分量

構建圓方樹時我們處理點雙聯通分量(一般無向圖中兩個點、一條邊的也算一個點雙)

具體做法是原圖中每個點是圓點

對于每個點雙,我們新建一個方點

點雙中原有的邊全部拆掉,而里面的圓點(原圖上的點)都向這個方點連邊

當然原圖中的點可能屬于多個點雙

舉個例子就是:

然后它就變成了一棵樹,然后什么樹鏈剖分、點分治、虛樹、樹形dp甚至LCT等各種(duliu)算法就可以在上面搞啦!唯一需要注意的是方點和圓點的維護方式可能不同

具體的構建過程寫法不唯一,可以一邊\(Tarjan\)一邊建樹,也可以存下屬于哪些點雙然后推倒重建

推倒重建版:

void Tarjan(int u, int fa) {dfn[u] = low[u] = ++idx;for (int i = G.head[u]; ~i; i = G.edge[i].next) {int v = G.edge[i].v;if (v == fa) continue;if (!dfn[v]) {stk[stop++] = v;Tarjan(v, u);low[u] = std::min(low[u], low[v]);if (low[v] >= dfn[u]) {int p; ++tot;do {p = stk[--stop];bel[p].push_back(tot);} while (p ^ v);bel[u].push_back(tot);}} else low[u] = std::min(low[u], dfn[v]);} } void rebuild() {G.init();for (int i = 1; i <= N; ++i) for (int j = 0; j < bel[i].size(); ++j)G.insert(i, bel[i][j]); }

性質

這樣建出的圓方樹具有以下性質:

  • 顯然建出的是一堆無根樹構成的森林,原圖上聯通的點圓方樹(森林)上也聯通
  • 相鄰的點形狀必定不同
  • 所有度數\(\ge 1\)的圓點在原圖中都是割點
  • 例題

    還是要從例題入手,才能發現圓方樹性質的妙用,所以:

    UOJ#30[Codeforces 487E]

    JZOJ3225[BJOI2013]load

    仙人掌的圓方樹

    upd 2019.4.9 咕了好久,我終于來填坑了!!

    好像上面那個叫廣義圓方樹,這個才是正統圓方樹來著,我又學錯順序了??

    仙人掌

    無向仙人掌是指一條邊至多在一個簡單環中的無向圖

    構建

    大體上類似于廣義圓方樹,但這里我們對一個環建方點,而不在同一個環上的兩個圓點直接連邊

    就比如:

    性質

    可能存在圓方邊和圓圓邊,但沒有方方邊

    然后容易發現原仙人掌的子仙人掌對應的圓方樹是整個圓方樹上的一個聯通塊

    例題

    洛谷模板題

    首先建出圓方樹,然后考慮賦邊權

    為了是原仙人掌上的最短路對應圓方樹上兩點間的路徑,我們按如下方式賦邊權:

  • 指定一個圓點為圓方樹的根,然后我們把一個方點的父親叫做這個方點對應的環的根
  • 若一個在環上的圓點不是環的根,它到對應方點的邊權為到環的根的最短距離
  • 環的根到環所對應的方點的邊權為0
  • 然后仿照在樹上查詢兩點路徑一樣

    但是這里需要分類討論:

  • \(lca\)是圓點,那么答案就是路徑長度
  • \(lca\)是方點,則找到進入這個環的兩個點,這兩個點之間的有兩條路徑,比較一下選較短的
  • 如何找到2中的兩個點呢?

    如果寫的是倍增,可以方便求出

    如果寫的是樹鏈剖分,這兩個點有兩種情況:1.一個是dfs序比\(lca\)大1的點,一個是最后經過的\(top\);2.最后經過的兩個\(top\)

    環上路徑可以用距離前綴和,再記錄一下每個環的邊權和求出

    代碼(倍增)

    #include <cstdio> #include <cstring> #include <iostream> #define MAXN 10005 #define MAXM 20005typedef long long LL; struct Graph {struct Edge {int v, next; LL w;Edge(int _v = 0, int _n = 0, LL _w = 0):v(_v), next(_n), w(_w) {}} edge[MAXM << 2];int head[MAXN << 1], cnt;void init() { memset(head, -1, sizeof head); cnt = 0; }void add_edge(int u, int v, int w) { edge[cnt] = Edge(v, head[u], w); head[u] = cnt++; }void insert(int u, int v, int w) { add_edge(u, v, w); add_edge(v, u, w); } };char gc(); LL read(); void Tarjan(int, int); LL query(int, int); void dfs(int);int N, M, Q; int dep[MAXN << 1], dist[MAXN << 1], anc[MAXN << 1][17];//圓方樹上的深度、到根的距離、祖先 LL sum[MAXN], sumd[MAXN];//sum:距離前綴和,也就是搜索樹上到根的距離。sumd:每個環的邊權和 int dfn[MAXN], low[MAXN], bcc_cnt, idx, stk[MAXN], top;;//Tarjan用到的 Graph G, T;//G:原圖。T:圓方樹 int main() {G.init(), T.init();N = read(), M = read(), Q = read();for (int i = 1; i <= M; ++i) {int u = read(), v = read(); LL w = read();G.insert(u, v, w);}Tarjan(1, 0);dfs(1);while (Q--) {int u = read(), v = read();printf("%lld\n", query(u, v));}return 0; } inline char gc() {static char buf[1000000], *p1, *p2;if (p1 == p2) p1 = (p2 = buf) + fread(buf, 1, 1000000, stdin);return p1 == p2 ? EOF : *p2++; } inline LL read() {LL res = 0, op; char ch = gc();while (ch != '-' && (ch < '0' || ch > '9')) ch = gc();op = (ch == '-' ? ch = gc(), -1 : 1);while (ch >= '0' && ch <= '9') res = (res << 1) + (res << 3) + ch - '0', ch = gc();return res * op; } void Tarjan(int u, int fa) {dfn[u] = low[u] = ++idx;stk[top++] = u;for (int i = G.head[u]; ~i; i = G.edge[i].next) {int v = G.edge[i].v; LL w = G.edge[i].w;if (v == fa) continue;if (!dfn[v]) {sum[v] = sum[u] + w;Tarjan(v, u);low[u] = std::min(low[u], low[v]);if (low[v] > dfn[u]) T.insert(u, v, w);//非樹邊只可能是返祖邊,可以這樣判 } else if (dfn[v] < low[u]) {//這里這樣判也是一樣的原因 low[u] = dfn[v];++bcc_cnt;sumd[bcc_cnt] = sum[u] + w - sum[v];for(int j = top - 1; stk[j] ^ v; --j) {int p = stk[j];T.insert(N + bcc_cnt, p, std::min(sum[p] - sum[v], sumd[bcc_cnt] - sum[p] + sum[v]));}T.insert(N + bcc_cnt, v, 0);}}--top; } void dfs(int u) {dep[u] = dep[anc[u][0]] + 1;for (int i = 1; i < 17 && anc[u][i - 1]; ++i) anc[u][i] = anc[anc[u][i - 1]][i - 1];for (int i = T.head[u]; ~i; i = T.edge[i].next) {int v = T.edge[i].v; LL w = T.edge[i].w;if (v == anc[u][0]) continue;dist[v] = dist[u] + w;anc[v][0] = u, dfs(v);} } LL query(int x, int y) {int lca; LL res = dist[x] + dist[y];if (dep[x] < dep[y]) std::swap(x, y);for (int i = 16; i >= 0; --i) if (dep[anc[x][i]] >= dep[y]) x = anc[x][i];if (x == y) lca = x;else {for (int i = 16; i >= 0; --i) if (anc[x][i] ^ anc[y][i]) x = anc[x][i], y = anc[y][i];lca = anc[x][0];}if (lca <= N) return res - (dist[lca] << 1);//lca是圓點 else {//lca是方點 if (dfn[x] > dfn[y]) std::swap(x, y);return res - dist[x] - dist[y] + std::min(sum[y] - sum[x], sumd[lca - N] - sum[y] + sum[x]);} } //Rhein_E

    轉載于:https://www.cnblogs.com/Rhein-E/p/10617334.html

    總結

    以上是生活随笔為你收集整理的[学习笔记]圆方树广义圆方树的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 黑人干亚洲 | 华人永久免费 | 日本a在线观看 | 一级黄色小视频 | 日韩一级欧美 | 青青国产精品 | 国产精成人 | a免费在线 | 一区视频在线播放 | 日本不卡一二 | 夜夜操夜夜操 | 日本欧美一区 | 超污巨黄的小短文 | 久久嫩草精品久久久久 | 国产熟妇与子伦hd | 我把护士日出水了视频90分钟 | 一个人看的www视频在线观看 | 日韩少妇高潮抽搐 | 亚洲婷婷综合网 | 男女做爰猛烈刺激 | 国产麻豆精品在线 | 欧美丰满少妇人妻精品 | 久草网在线视频 | 久久久久久久一区二区 | heyzo朝桐光一区二区 | 自拍偷拍日韩精品 | 亚欧美日韩 | 日韩av一| 国产精品久久福利 | 久久久久久久久电影 | 窝窝午夜影院 | 久色视频在线观看 | 久久久久久久伊人 | av免费在线电影 | 黄色特级大片 | 久久久久久欧美 | 性工作者十日谈 | 国产性一乱一性一伧一色 | 国产特级淫片免费看 | 天堂网久久 | 欧美 亚洲 另类 偷偷 自拍 | 亚洲男人的天堂网站 | 无码国产精品一区二区色情男同 | 日韩网站在线 | 麻豆一区二区三区在线观看 | 天堂a在线| 91蜜桃在线 | 蜜乳av一区二区 | 激情九月婷婷 | 亚洲免费在线视频 | 久久爱网 | 国产一区二区三区视频在线播放 | 日韩黄色一级片 | 久久久久久91 | 在线看v片 | 欧美少妇喷水 | 国产精品毛片一区二区在线看 | 麻豆精品网站 | 亚洲激情自拍偷拍 | 天天舔天天干天天操 | 精品欧美久久久 | 黄色的视频网站 | 国产成人久久婷婷精品流白浆 | 国产精品羞羞答答 | 中文字幕性| 国产精品无码电影在线观看 | 久久综合九色综合网站 | 国产精品国产a级 | 免费av网址在线观看 | 免费成人av在线播放 | 亚洲性色视频 | 91麻豆精品国产91久久久更新时间 | 4438激情网 | 五月天精品视频 | 中文字幕人成人乱码亚洲电影 | 在线看黄网址 | 亚洲中文一区二区 | 免费一区| 女人久久久 | 成人网免费看 | av免费大全 | 日韩欧美成人一区二区 | 欧洲金发美女大战黑人 | 亚洲久久色 | 国产又粗又猛又爽又黄无遮挡 | 天堂中文在线官网 | 美女脱裤子让男人捅 | www.av.cn| 三级影片在线免费观看 | 美女啪啪网站 | 成年人午夜影院 | 综合久久久久久久久久久 | 99视频在线看 | 91黄色小视频 | 又黄又刺激的视频 | 欧美激情视频网站 | 国产一级网站 | 一级特黄色大片 | 国产激情91 |