forked from Punyaslok/snippets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
directed_mst.cpp
56 lines (45 loc) · 1.22 KB
/
directed_mst.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// Directed minimum spanning tree
//
// Given a directed weighted graph and root node, computes the minimum spanning
// directed tree (arborescence) on it.
//
// Complexity: O(N * M), where N is the number of nodes, and M the number of edges
struct Edge { int x, y, w; };
int dmst(int N, vector<Edge> E, int root) {
const int oo = 1e9;
vector<int> cost(N), back(N), label(N), bio(N);
int ret = 0;
for (;;) {
REP(i, N) cost[i] = oo;
for (auto e : E) {
if (e.x == e.y) continue;
if (e.w < cost[e.y]) cost[e.y] = e.w, back[e.y] = e.x;
}
cost[root] = 0;
REP(i, N) if (cost[i] == oo) return -1;
REP(i, N) ret += cost[i];
int K = 0;
REP(i, N) label[i] = -1;
REP(i, N) bio[i] = -1;
REP(i, N) {
int x = i;
for (; x != root && bio[x] == -1; x = back[x]) bio[x] = i;
if (x != root && bio[x] == i) {
for (; label[x] == -1; x = back[x]) label[x] = K;
++K;
}
}
if (K == 0) break;
REP(i, N) if (label[i] == -1) label[i] = K++;
for (auto &e : E) {
int xx = label[e.x];
int yy = label[e.y];
if (xx != yy) e.w -= cost[e.y];
e.x = xx;
e.y = yy;
}
root = label[root];
N = K;
}
return ret;
}