缩点板子求调。码风较幼稚但自认为较易阅读。(#1 #4 #5 #7 WA)
查看原帖
缩点板子求调。码风较幼稚但自认为较易阅读。(#1 #4 #5 #7 WA)
205199
紪絽楼主2024/10/8 19:50
#include <bits/stdc++.h>
using namespace std;

int n, m, ans, a[10001];
vector<int> g[10001], G[10001];
// 原图 缩点后的图
int tot, dfn[10001], low[10001], top, stk[10001], instk[10001];
// dfn 序  dfn 编号  low 编号  栈顶  栈  是否在栈中
int SCC, scc[10001], sz[10001];
// SCC 总数  节点所在的 SCC 编号  SCC 大小  
int in[10001]; queue<int> q; int f[10001];
// 入度  topo  最终答案

void tarjan(int u)
{
    dfn[u] = ++tot, low[u] = dfn[u];
    stk[++top] = u, instk[u] = 1;
    
    for (auto v : g[u])
    {
        if (dfn[v] == 0)
            tarjan(v), low[u] = min(low[u], low[v]);
        else if (instk[v])
            low[u] = min(low[u], dfn[v]);
    }
    
    if (dfn[u] == low[u])
    {
        SCC++;
        while (stk[top] != u)
        {
            scc[stk[top]] = SCC, sz[SCC] += a[stk[top]];
            instk[top] = 0; top--;
        }
        scc[u] = SCC, sz[SCC] += a[u];
        instk[u] = 0, top--;
    }
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> a[i];
    
    for (int i = 1; i <= m; i++)
    {
        int u, v; cin >> u >> v;
        g[u].push_back(v);
    }
    
    for (int i = 1; i <= n; i++)
        if (!dfn[i]) tarjan(i);
    
    for (int u = 1; u <= n; u++)
        for (auto v : g[u])
            if (scc[u] != scc[v])
                G[scc[u]].push_back(scc[v]), in[scc[v]]++;
    
    for (int i = 1; i <= SCC; i++)
    {
        f[i] = sz[i];
        if (!in[i]) 
            q.push(i);
    }
    
    while (!q.empty())
    {
        int u = q.front(); q.pop();
        for (auto v : G[u])
        {
            in[v]--;
            if (!in[v]) q.push(v);
            f[v] = max(f[v], f[u] + sz[v]);
        }
    }
    
    for (int i = 1; i <= SCC; i++)
        ans = max(ans, f[i]);
    cout << ans;
    
    return 0;
}
2024/10/8 19:50
加载中...