40pts,tarjan + topo,大佬求调qwq
查看原帖
40pts,tarjan + topo,大佬求调qwq
768692
InoriILU楼主2023/10/13 17:10

大佬救命

#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]{};
NodeType head[MAXN]{};
EdgeType count{};
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)
{
    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 (group[i] == i && indegree[i] == 0)
        {
            Q.push(i);
            dis[i] = newval[i];
        }
    }

    while (Q.size())
    {
        now = Q.front();
        Q.pop();
        for (EdgeType i = head[now], end{}; i; i = G[i].next)
        {
            end = G[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 <= n; 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]);
    }

    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 < newcnt; i++)
    {
        if (group[s[i]] != group[t[i]])
        {
            addedge(group[s[i]], group[t[i]]);
            indegree[t[i]]++;
        }
    }

    cout << topo() << endl;
}

2023/10/13 17:10
加载中...