tarjan缩点
强连通定义:在有向图 中,对于点集 , 点集中的任意两点都可达,则称 为强连通。
考虑建出图的 dfs 树,则原图上的边可以转换为三种边:
坑:
-
要写两个连边函数,把第二个函数的
siz
写成了tot
,调了我一个晚上…1
2
3
4
5
6
7
8
9
10
11
12
13
14
15void addline(int u, int v) {
tot++;
l[tot].from = u;
l[tot].to = v;
l[tot].next = hl[u];
hl[u] = tot;
}
void addedge(int u, int v) {
siz++;
e[siz].from = u;
e[siz].to = v;
e[siz].next = he[u];
he[u] = siz; //就是这里!
} -
由于存边的时候只存了一个点的后继节点,所以要根据节点 更新节点
如图,灰色的节点都已经更新完了,现在是操作 节点,使得 、、 的答案更新。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20void sort() {
std::queue <int> q;
for (int i = 1; i <= n; i++) {
if (idx[i] == i) {
if (!deg[i]) {
q.push(i);
ans[i] = scc[i];
}
}
}
while (q.size()) {
int u = q.front(); q.pop();
for (int i = he[u]; i; i = e[i].next) {
int v = e[i].to;
ans[v] = std::max(ans[v], scc[v] + ans[u]);
deg[v]--;
if (deg[v] == 0) q.push(v);
}
}
} -
把
idx[v]
写成了idx[i]
(i
是边,v
是点) -
把
idx[v]
写成了v
1
2
3
4
5
6
7
8
9
10void init() {
for (int i = 1, u, v; i <= tot; i++) {
u = l[i].from;
v = l[i].to;
if (idx[u] != idx[v]) {
addedge(idx[u], idx[v]);
deg[idx[v]]++;//就是这里
}
}
}
总结:一定要清楚每个变量和数组代表的意义是什么!
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Cauphenuny's Blog!
评论