Loading docs/graph/mdst.md +110 −115 Original line number Diff line number Diff line ## 最小树形图 有向图上的最小生成树(Minimum Directed Spanning Tree)称为最小树形图。 Loading Loading @@ -90,7 +89,6 @@ Tarjan的算法分为**收缩** 与 **伸展**两个过程。接下来先介绍* ### 代码 ```cpp #include <bits/stdc++.h> using namespace std; Loading Loading @@ -124,14 +122,14 @@ struct Heap { Heap *merge(Heap *x, Heap *y) { if (!x) return y; if (!y) return x; if (x->e->w + x->constant > y->e->w + y->constant) swap(x, y); if (x->e->w + x->constant > y->e->w + y->constant) swap(x, y); x->push(); x->rch = merge(x->rch, y); if (!x->lch || x->lch->rk < x->rch->rk) swap(x->lch, x->rch); if (x->rch) x->rk = x->rch->rk + 1; else x->rk = 1; if (!x->lch || x->lch->rk < x->rch->rk) swap(x->lch, x->rch); if (x->rch) x->rk = x->rch->rk + 1; else x->rk = 1; return x; } Edge *extract(Heap *&x) { Loading @@ -152,11 +150,12 @@ void contract() { // 将图上的每一个结点与其相连的那些结点进行记录。 for (int i = 1; i <= n; i++) { queue<Heap *> q; for (int j = 0; j < in[i].size(); j++) q.push(new Heap(&in[i][j])); for (int j = 0; j < in[i].size(); j++) q.push(new Heap(&in[i][j])); while (q.size() > 1) { Heap *u = q.front(); q.pop(); Heap *v = q.front(); q.pop(); Heap *u = q.front(); q.pop(); Heap *v = q.front(); q.pop(); q.push(merge(u, v)); } Q[i] = q.front(); Loading Loading @@ -184,9 +183,9 @@ void contract() { ll expand(int x, int r); ll expand_iter(int x) { ll r = 0; for (int u = nxt[x]; u != x; u = nxt[u]) { if (ed[u]->w0 >= INF) return INF; for (int u = nxt[x]; u != x; u = nxt[u]) { if (ed[u]->w0 >= INF) return INF; else r += expand(ed[u]->v, u) + ed[u]->w0; } Loading @@ -194,40 +193,36 @@ ll expand_iter(int x) { } ll expand(int x, int t) { ll r = 0; for (; x != t; x = fa[x]) { for (; x != t; x = fa[x]) { r += expand_iter(x); if (r >= INF) return INF; } return r; } void link(int u, int v, int w) { in[v].push_back({u, v, w, w}); } void link(int u, int v, int w) { in[v].push_back({u, v, w, w}); } int main() { int rt; scanf("%d %d %d", &n, &m, &rt); for (int i = 0; i < m; i++) { for (int i = 0; i < m; i++) { int u, v, w; scanf("%d %d %d", &u, &v, &w); link(u, v, w); } // 保证强连通 for (int i = 1; i <= n; i++) link(i > 1 ? i - 1 : n, i, INF); for (int i = 1; i <= n; i++) link(i > 1 ? i - 1 : n, i, INF); contract(); ll ans = expand(rt, n); if (ans >= INF) puts("-1"); else printf("%lld\n", ans); if (ans >= INF) puts("-1"); else printf("%lld\n", ans); return 0; } ``` ## 参考文献 Uri Zwick. (2013), [Directed Minimum Spanning Trees](http://www.cs.tau.ac.il/~zwick/grad-algo-13/directed-mst.pdf) , Lecture notes on“Analysis of Algorithms” https://riteme.site/blog/2018-6-18/mdst.html#_3 <https://riteme.site/blog/2018-6-18/mdst.html#_3> Loading
docs/graph/mdst.md +110 −115 Original line number Diff line number Diff line ## 最小树形图 有向图上的最小生成树(Minimum Directed Spanning Tree)称为最小树形图。 Loading Loading @@ -90,7 +89,6 @@ Tarjan的算法分为**收缩** 与 **伸展**两个过程。接下来先介绍* ### 代码 ```cpp #include <bits/stdc++.h> using namespace std; Loading Loading @@ -124,14 +122,14 @@ struct Heap { Heap *merge(Heap *x, Heap *y) { if (!x) return y; if (!y) return x; if (x->e->w + x->constant > y->e->w + y->constant) swap(x, y); if (x->e->w + x->constant > y->e->w + y->constant) swap(x, y); x->push(); x->rch = merge(x->rch, y); if (!x->lch || x->lch->rk < x->rch->rk) swap(x->lch, x->rch); if (x->rch) x->rk = x->rch->rk + 1; else x->rk = 1; if (!x->lch || x->lch->rk < x->rch->rk) swap(x->lch, x->rch); if (x->rch) x->rk = x->rch->rk + 1; else x->rk = 1; return x; } Edge *extract(Heap *&x) { Loading @@ -152,11 +150,12 @@ void contract() { // 将图上的每一个结点与其相连的那些结点进行记录。 for (int i = 1; i <= n; i++) { queue<Heap *> q; for (int j = 0; j < in[i].size(); j++) q.push(new Heap(&in[i][j])); for (int j = 0; j < in[i].size(); j++) q.push(new Heap(&in[i][j])); while (q.size() > 1) { Heap *u = q.front(); q.pop(); Heap *v = q.front(); q.pop(); Heap *u = q.front(); q.pop(); Heap *v = q.front(); q.pop(); q.push(merge(u, v)); } Q[i] = q.front(); Loading Loading @@ -184,9 +183,9 @@ void contract() { ll expand(int x, int r); ll expand_iter(int x) { ll r = 0; for (int u = nxt[x]; u != x; u = nxt[u]) { if (ed[u]->w0 >= INF) return INF; for (int u = nxt[x]; u != x; u = nxt[u]) { if (ed[u]->w0 >= INF) return INF; else r += expand(ed[u]->v, u) + ed[u]->w0; } Loading @@ -194,40 +193,36 @@ ll expand_iter(int x) { } ll expand(int x, int t) { ll r = 0; for (; x != t; x = fa[x]) { for (; x != t; x = fa[x]) { r += expand_iter(x); if (r >= INF) return INF; } return r; } void link(int u, int v, int w) { in[v].push_back({u, v, w, w}); } void link(int u, int v, int w) { in[v].push_back({u, v, w, w}); } int main() { int rt; scanf("%d %d %d", &n, &m, &rt); for (int i = 0; i < m; i++) { for (int i = 0; i < m; i++) { int u, v, w; scanf("%d %d %d", &u, &v, &w); link(u, v, w); } // 保证强连通 for (int i = 1; i <= n; i++) link(i > 1 ? i - 1 : n, i, INF); for (int i = 1; i <= n; i++) link(i > 1 ? i - 1 : n, i, INF); contract(); ll ans = expand(rt, n); if (ans >= INF) puts("-1"); else printf("%lld\n", ans); if (ans >= INF) puts("-1"); else printf("%lld\n", ans); return 0; } ``` ## 参考文献 Uri Zwick. (2013), [Directed Minimum Spanning Trees](http://www.cs.tau.ac.il/~zwick/grad-algo-13/directed-mst.pdf) , Lecture notes on“Analysis of Algorithms” https://riteme.site/blog/2018-6-18/mdst.html#_3 <https://riteme.site/blog/2018-6-18/mdst.html#_3>