vector<int> E[N]; int deg[N]; // 入度 int dp[N]; // 到达某点的最大点权和 inlinebooltopo(int n){ for (int u = 1; u <= n; ++u) { for (auto v : E[u]) deg[v] += 1;// 统计入度 }
// DP更新low[u] for (auto v : E[u]) { if (!dfsn[v]) eachTarjan(v), low[u] = std::min(low[u], low[v]); elseif (!fa[v]) low[u] = std::min(low[u], dfsn[v]); }
// u是SCC的根 if (low[u] == dfsn[u]) { int top; do { top = S.top(); S.pop(); // 出栈 fa[top] = u; // 记录u的子节点的根为u } while (top != u); // 不断弹出直到根u弹出为止 } }
inlinevoidtarjan(int n){ // Tarjan for (int u = 1; u <= n; ++u) { if (!dfsn[u]) eachTarjan(u); } // 重构图 将子树的性质嫁接到SCC的根上 for (int u = 1; u <= n; ++u) { for (auto v : E[u]) { if (fa[u] != fa[v]) Etmp[fa[u]].push_back(fa[v]); } // 存储新的边 wtmp[fa[u]] += w[u]; // 存储新的边权 } for (int u = 1; u <= n; ++u) { w[u] = wtmp[u]; E[u] = Etmp[u]; std::sort(E[u].begin(), E[u].end()); E[u].erase(std::unique(E[u].begin(), E[u].end()), E[u].end()); } }
int deg[N], dp[N]; inlinevoidtopo(int n){ for (int u = 1; u <= n; ++u) { for (auto v : E[u]) deg[v] += 1; } std::queue<int> Q; for (int u = 1; u <= n; ++u) { if (!deg[u] && u == fa[u]) Q.push(u), dp[u] = w[u]; } while (!Q.empty()) { int u = Q.front(); Q.pop(); for (auto to : E[u]) { deg[to] -= 1; if (!deg[to]) Q.push(to), dp[to] = std::max(dp[to], dp[u] + w[to]); } } int ans = 0; for (int u = 1; u <= n; ++u) ans = std::max(ans, dp[u]); printf("%d", ans); }
voideachT(){ int n = read(), m = read(); for (int i = 1; i <= n; i++) w[i] = read(); for (int i = 1; i <= m; i++) { int u = read(), v = read(); E[u].push_back(v); } tarjan(n); topo(n); }