在強連通分量內任意兩點互達,且可無限次遍歷。因此:
father[u]w[root] += w[u]father[u] != father[v] 添加縮點後的邊father[S] 起跑 SPFA (隊列優化 Bellman-Ford),距離數組 dist[v] = max(dist[v], dist[u] + w[v])max(dist[father[bar]])
void tarjan(int u) {
dfn[u] = low[u] = ++num;
stack[++top] = u; inStack[u] = true;
for (int i = hh[u]; i; i = b[i].next) {
int v = b[i].v;
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (inStack[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) { // 找到 SCC 根
inStack[u] = false;
father[u] = u;
while (stack[top] != u) {
w[u] += w[stack[top]];
father[stack[top]] = u;
inStack[stack[top--]] = false;
}
top--;
}
}
void spfa() {
memset(inQueue, 0, sizeof(inQueue));
int h = 0, t = 0;
q[++t] = s; dist[s] = w[s]; inQueue[s] = 1;
while (h < t) {
int u = q[++h]; inQueue[u] = 0;
for (int i = hhh[u]; i; i = ss[i].next) {
int v = ss[i].v;
if (dist[u] + w[v] > dist[v]) {
dist[v] = dist[u] + w[v];
if (!inQueue[v]) {
q[++t] = v;
inQueue[v] = 1;
}
}
}
}
}
s = father[s],若起點在 SCC 內需用根節點dist[father[bar]]本題是「強連通分量縮點 + DAG 最長路」的經典模板題,掌握此模式可解決大類圖論優化問題。