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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法笔记--支配树

發(fā)布時(shí)間:2024/1/8 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法笔记--支配树 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.DAG
按照拓?fù)湫驈男〉酱筇幚?#xff0c;對于每個(gè)節(jié)點(diǎn),將所有連接它的點(diǎn)的lca求出來,它在支配樹上的父親就是這個(gè)lca。
2.一般圖
模板:

vector<int> g[N], rg[N], tg[N], G[N]; int in[N], dfn[N], rak[N], fa[N], sdom[N], idom[N], val[N], ufs[N], cnt; LL sz[N]; void dfs1(int u) {sdom[u] = dfn[u] = ++cnt;rak[cnt] = u;for (int v : g[u]) {if(!dfn[v]) {fa[v] = u;dfs1(v);}} } void dfs2(int u) {sz[u] = 1;for (int v : G[u]) {dfs2(v);sz[u] += sz[v];} } int Find(int x) {if(ufs[x] == x) return x;int fx = Find(ufs[x]);if(sdom[val[ufs[x]]] < sdom[val[x]]) val[x] = val[ufs[x]];return ufs[x] = fx; } void lengauer_tarjan(int n) {///初始化cnt = 0;for (int i = 0; i <= n; ++i) {sz[i] = dfn[i] = in[i] = 0;ufs[i] = val[i] = i;g[i].clear(); ///原圖rg[i].clear();///反圖tg[i].clear();G[i].clear();}///輸入///從n出發(fā)g[0].pb(n), rg[n].pb(0);///從入度為0的出發(fā)for (int i = 1; i <= n; ++i) if(!in[i]) g[0].pb(i), rg[i].pb(0);dfs1(0);for (int i = cnt; i >= 2; --i) {int u = rak[i];for (int v : rg[u]) {if(!dfn[v]) continue;Find(v);sdom[u] = min(sdom[u], sdom[val[v]]);}ufs[u] = fa[u];tg[rak[sdom[u]]].pb(u);for (int v : tg[fa[u]]) {Find(v);if(sdom[val[v]] == sdom[v]) idom[v] = rak[sdom[v]];else idom[v] = val[v];}tg[fa[u]].clear();}for (int i = 1; i <= cnt; ++i) {int u = rak[i];if(idom[u] != rak[sdom[u]]) idom[u] = idom[idom[u]];}for (int i = 1; i <= n; ++i) if(dfn[i]) G[idom[i]].pb(i);dfs2(0);for (int i = 1; i <= n; ++i) printf("%d%c", dfn[i]?sz[i]:0, " \n"[i==n]); }

例題1:P2597 [ZJOI2012]災(zāi)難
代碼:

#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //headconst int N = 1e5 + 5; vector<int> g[N], rg[N], tg[N], G[N]; int in[N], dfn[N], rak[N], fa[N], sdom[N], idom[N], val[N], ufs[N], sz[N], cnt; void dfs1(int u) {sdom[u] = dfn[u] = ++cnt;rak[cnt] = u;for (int v : g[u]) {if(!dfn[v]) {fa[v] = u;dfs1(v);}} } void dfs2(int u) {sz[u] = 1;for (int v : G[u]) {dfs2(v);sz[u] += sz[v];} } int Find(int x) {if(ufs[x] == x) return x;int fx = Find(ufs[x]);if(sdom[val[ufs[x]]] < sdom[val[x]]) val[x] = val[ufs[x]];return ufs[x] = fx; } void lengauer_tarjan(int n) {///初始化cnt = 0;for (int i = 0; i <= n; ++i) {dfn[i] = in[i] = 0;ufs[i] = val[i] = i;g[i].clear();rg[i].clear();tg[i].clear();G[i].clear();}///輸入for (int i = 1; i <= n; ++i) {int x;while(~scanf("%d", &x) && x) {g[x].pb(i);in[i]++;rg[i].pb(x);}}///輸入for (int i = 1; i <= n; ++i) if(!in[i]) g[0].pb(i), rg[i].pb(0);dfs1(0);for (int i = n+1; i >= 2; --i) {int u = rak[i];for (int v : rg[u]) {Find(v);sdom[u] = min(sdom[u], sdom[val[v]]);}ufs[u] = fa[u];tg[rak[sdom[u]]].pb(u);for (int v : tg[fa[u]]) {Find(v);if(sdom[val[v]] == sdom[v]) idom[v] = rak[sdom[v]];else idom[v] = val[v];}tg[fa[u]].clear();}for (int i = 1; i <= n+1; ++i) {int u = rak[i];if(idom[u] != rak[sdom[u]]) idom[u] = idom[idom[u]];}for (int i = 1; i <= n; ++i) G[idom[i]].pb(i);dfs2(0);for (int i = 1; i <= n; ++i) printf("%d\n", sz[i]-1); } int n; int main() {scanf("%d", &n);lengauer_tarjan(n);return 0; }

例題2:P5180 【模板】支配樹
代碼:

#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //headconst int N = 2e5 + 5; vector<int> g[N], rg[N], tg[N], G[N]; int in[N], dfn[N], rak[N], fa[N], sdom[N], idom[N], val[N], ufs[N], sz[N], cnt; void dfs1(int u) {sdom[u] = dfn[u] = ++cnt;rak[cnt] = u;for (int v : g[u]) {if(!dfn[v]) {fa[v] = u;dfs1(v);}} } void dfs2(int u) {sz[u] = 1;for (int v : G[u]) {dfs2(v);sz[u] += sz[v];} } int Find(int x) {if(ufs[x] == x) return x;int fx = Find(ufs[x]);if(sdom[val[ufs[x]]] < sdom[val[x]]) val[x] = val[ufs[x]];return ufs[x] = fx; } void lengauer_tarjan(int n) {///初始化cnt = 0;for (int i = 0; i <= n; ++i) {dfn[i] = in[i] = 0;ufs[i] = val[i] = i;g[i].clear();rg[i].clear();tg[i].clear();G[i].clear();}///輸入int m, u, v;scanf("%d", &m);for (int i = 1; i <= m; ++i) {scanf("%d %d", &u, &v);g[u].pb(v);in[v]++;rg[v].pb(u);}///輸入g[0].pb(1), rg[1].pb(0);dfs1(0);for (int i = n+1; i >= 2; --i) {int u = rak[i];for (int v : rg[u]) {Find(v);sdom[u] = min(sdom[u], sdom[val[v]]);}ufs[u] = fa[u];tg[rak[sdom[u]]].pb(u);for (int v : tg[fa[u]]) {Find(v);if(sdom[val[v]] == sdom[v]) idom[v] = rak[sdom[v]];else idom[v] = val[v];}tg[fa[u]].clear();}for (int i = 1; i <= n+1; ++i) {int u = rak[i];if(idom[u] != rak[sdom[u]]) idom[u] = idom[idom[u]];}for (int i = 1; i <= n; ++i) G[idom[i]].pb(i);dfs2(0);for (int i = 1; i <= n; ++i) printf("%d%c", sz[i], " \n"[i==n]); } int n; int main() {scanf("%d", &n);lengauer_tarjan(n);return 0; }

例題3:HDU 4694
代碼:

#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //headconst int N = 5e4 + 5; vector<int> g[N], rg[N], tg[N], G[N]; int in[N], dfn[N], rak[N], fa[N], sdom[N], idom[N], val[N], ufs[N], cnt; LL sz[N]; void dfs1(int u) {sdom[u] = dfn[u] = ++cnt;rak[cnt] = u;for (int v : g[u]) {if(!dfn[v]) {fa[v] = u;dfs1(v);}} } void dfs2(int u, LL d) {sz[u] = d;for (int v : G[u]) {dfs2(v, d+v);} } int Find(int x) {if(ufs[x] == x) return x;int fx = Find(ufs[x]);if(sdom[val[ufs[x]]] < sdom[val[x]]) val[x] = val[ufs[x]];return ufs[x] = fx; } void lengauer_tarjan(int n) {///初始化cnt = 0;for (int i = 0; i <= n; ++i) {sz[i] = dfn[i] = in[i] = 0;ufs[i] = val[i] = i;g[i].clear();rg[i].clear();tg[i].clear();G[i].clear();}///輸入int m, u, v;scanf("%d", &m);for (int i = 1; i <= m; ++i) {scanf("%d %d", &u, &v);g[u].pb(v);in[v]++;rg[v].pb(u);}///輸入g[0].pb(n), rg[n].pb(0);dfs1(0);for (int i = cnt; i >= 2; --i) {int u = rak[i];for (int v : rg[u]) {if(!dfn[v]) continue;Find(v);sdom[u] = min(sdom[u], sdom[val[v]]);}ufs[u] = fa[u];tg[rak[sdom[u]]].pb(u);for (int v : tg[fa[u]]) {Find(v);if(sdom[val[v]] == sdom[v]) idom[v] = rak[sdom[v]];else idom[v] = val[v];}tg[fa[u]].clear();}for (int i = 1; i <= cnt; ++i) {int u = rak[i];if(idom[u] != rak[sdom[u]]) idom[u] = idom[idom[u]];}for (int i = 1; i <= n; ++i) if(dfn[i]) G[idom[i]].pb(i);dfs2(0, 0);for (int i = 1; i <= n; ++i) printf("%lld%c", dfn[i]?sz[i]:0, " \n"[i==n]); } int n; int main() {while(~scanf("%d", &n)) lengauer_tarjan(n);return 0; }

例題4:Codechef Counting on a directed graph
代碼:

#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> using namespace std; #define y1 y11 #define fi first #define se second #define pi acos(-1.0) #define LL long long //#define mp make_pair #define pb emplace_back #define ls rt<<1, l, m #define rs rt<<1|1, m+1, r #define ULL unsigned LL #define pll pair<LL, LL> #define pli pair<LL, int> #define pii pair<int, int> #define piii pair<pii, int> #define pdd pair<double, double> #define mem(a, b) memset(a, b, sizeof(a)) #define debug(x) cerr << #x << " = " << x << "\n"; #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); //headconst int N = 1e5 + 5; vector<int> g[N], rg[N], tg[N], G[N]; int in[N], dfn[N], rak[N], fa[N], sdom[N], idom[N], val[N], ufs[N], cnt; LL sz[N]; void dfs1(int u) {sdom[u] = dfn[u] = ++cnt;rak[cnt] = u;for (int v : g[u]) {if(!dfn[v]) {fa[v] = u;dfs1(v);}} } void dfs2(int u) {sz[u] = 1;for (int v : G[u]) {dfs2(v);sz[u] += sz[v];} } int Find(int x) {if(ufs[x] == x) return x;int fx = Find(ufs[x]);if(sdom[val[ufs[x]]] < sdom[val[x]]) val[x] = val[ufs[x]];return ufs[x] = fx; } void lengauer_tarjan(int n) {///初始化cnt = 0;for (int i = 0; i <= n; ++i) {sz[i] = dfn[i] = in[i] = 0;ufs[i] = val[i] = i;g[i].clear(); ///原圖rg[i].clear();///反圖tg[i].clear();G[i].clear();}///輸入int m, u, v;scanf("%d", &m);for (int i = 1; i <= m; ++i) {scanf("%d %d", &u, &v);g[u].pb(v);in[v]++;rg[v].pb(u);}///從n出發(fā)g[0].pb(1), rg[1].pb(0);///從入度為0的出發(fā)dfs1(0);for (int i = cnt; i >= 2; --i) {int u = rak[i];for (int v : rg[u]) {if(!dfn[v]) continue;Find(v);sdom[u] = min(sdom[u], sdom[val[v]]);}ufs[u] = fa[u];tg[rak[sdom[u]]].pb(u);for (int v : tg[fa[u]]) {Find(v);if(sdom[val[v]] == sdom[v]) idom[v] = rak[sdom[v]];else idom[v] = val[v];}tg[fa[u]].clear();}for (int i = 1; i <= cnt; ++i) {int u = rak[i];if(idom[u] != rak[sdom[u]]) idom[u] = idom[idom[u]];}for (int i = 1; i <= n; ++i) if(dfn[i]) G[idom[i]].pb(i);dfs2(0);LL ans = 0, tot = 1;for (int v : G[1]) {ans += sz[v]*tot;tot += sz[v];}printf("%lld\n", ans); } int n; int main() {while(~scanf("%d", &n)) lengauer_tarjan(n);return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/widsom/p/11367512.html

總結(jié)

以上是生活随笔為你收集整理的算法笔记--支配树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。