40pts,tarjan + topo,大佬求调qwq

P3387 【模板】缩点

```cpp #include <iostream> #include <queue> #include <vector> const int MAXN{ 10000 + 5 }; const int MAXM{ 100000 + 5 }; typedef int NodeType; typedef int EdgeType; typedef long long DataType; struct Edge { NodeType end; EdgeType next; }; Edge G[MAXM * 2]{}, newG[MAXM * 2]{}; NodeType head[MAXN]{}, newhead[MAXN]{}; EdgeType count{}, newcount{}; DataType value[MAXN]{}; NodeType dfn[MAXN]{}, low[MAXN]{}, dn{}; NodeType stack[MAXN]{}, top{}; NodeType group[MAXN]{}; EdgeType newcnt{}; DataType newval[MAXN]{}; bool visit[MAXN]{}; NodeType s[MAXM]{}, t[MAXM]{}; NodeType indegree[MAXN]{}; DataType dis[MAXN]{}; NodeType n{}; EdgeType m{}; void addedge(NodeType start, NodeType end, Edge *G, NodeType *head, int &count) { G[++count].end = end; G[count].next = head[start]; head[start] = count; } void dfs(NodeType now = 1) { using std::min; visit[now] = true; stack[++top] = now; dfn[now] = low[now] = ++dn; // 将 low[now] 初始化为 dn 不会导致错误, 且一般都这么写 for (int i{ head[now] }, end{}; i; i = G[i].next) { end = G[i].end; if (!dfn[end]) //若为树边 { dfs(end); low[now] = min(low[now], low[end]); //因为儿子可能非割点,所以 low 可能会小 } else if (visit[end]) low[now] = min(low[now], dfn[end]); //若不为树边,判断 visit 与否? } if (dfn[now] == low[now]) { newcnt++; do { group[stack[top]] = newcnt; newval[newcnt] += value[stack[top]]; visit[stack[top--]] = false; } while (now != stack[top + 1]); } } DataType topo() { std::queue<NodeType> Q; NodeType now{}; DataType ans{}; for (EdgeType i = 1; i <= newcnt; i++) { if (indegree[i] == 0) { Q.push(i); dis[i] = newval[i]; } } while (Q.size()) { now = Q.front(); Q.pop(); for (EdgeType i = newhead[now], end{}; i; i = newG[i].next) { end = newG[i].end; dis[end] = std::max(dis[end], dis[now] + newval[end]); indegree[end]--; if (indegree[end] == 0) Q.push(end); } } for (NodeType i = 1; i <= newcnt; i++) ans = std::max(ans, dis[i]); return ans; } int main() { using namespace std; ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> n >> m; for (NodeType i = 1; i <= n; i++) cin >> value[i]; for (EdgeType i{}; i < m; i++) { cin >> s[i] >> t[i]; addedge(s[i], t[i], G, head, count); } for (NodeType i = 1; i <= n; i++) if (!dfn[i]) dfs(i); fill(head + 1, head + n + 1, 0); ::count = 0; for (EdgeType i = 0; i < m; i++) { if (group[s[i]] != group[t[i]]) { addedge(group[s[i]], group[t[i]], newG, newhead, newcount); indegree[group[t[i]]]++; } } cout << topo() << endl; } ``` 要注意开新数组存新边,入度存得也有问题,其他还有一些问题,请自己对比一下
by DAMDAM @ 2023-10-13 18:13:59


@[DAMDAM](/user/759326) 谢谢大哥qwq 我刚才调过了,数组不清没有太大影响(因为链式前向星只需要清head 主要是 topo 函数中压入队列的条件错了。
by InoriILU @ 2023-10-13 19:05:54


|