WA#8求调,马蜂极好,有思路说明
查看原帖
WA#8求调,马蜂极好,有思路说明
22716
神仙酱楼主2024/5/23 16:06

我的思路是,先缩点成dag,然后分别计算能到起点(上游)和起点能到的点(下游)的点权和。在计算上游点的时候,如果它恰好能到下游点去,那么说明可以行程一个回路,于是更新一次ans

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 3e5, M = 5e5;
int e[M], h[N], hs[N], hr[N], nxt[M], idx = 1;
int n, m;
void add(int h[], int a, int b) { e[idx] = b, nxt[idx] = h[a], h[a] = idx++; }

int low[N], dfn[N], id[N], sz[N], stmp, scc;
int f[N], g[N];
bool st[N];
stack<int> s;
void tarjan(int u) {
    dfn[u] = low[u] = ++stmp;
    s.push(u), st[u] = true;
    for (int i = h[u]; i; i = nxt[i]) {
        int j = e[i];
        if (!dfn[j]) {
            tarjan(j);
            low[u] = min(low[u], low[j]);
        } else if (st[j])
            low[u] = min(low[u], dfn[j]);
    }
    if (low[u] == dfn[u]) {
        ++scc;
        int y;
        do {
            y = s.top();
            s.pop(), st[y] = false;
            sz[id[y] = scc]++;
        } while (y != u);
    }
}

int ans, start;
signed main() {
#ifndef ONLINE_JUDGE
    freopen(".in", "r", stdin);  // freopen("a.out", "w", stdout);
#else
    cin.tie(0)->sync_with_stdio(0);
#endif
    cin >> n >> m;
    for (int i = 1; i <= m; ++i) {
        int a, b;
        cin >> a >> b;
        add(h, a, b);
    }
    for (int i = 1; i <= n; ++i)
        if (!dfn[i])
            tarjan(i);
    for (int u = 1; u <= n; ++u) {
        int a = id[u];
        for (int i = h[u]; i; i = nxt[i]) {
            int j = e[i], b = id[j];
            if (a != b)
                add(hs, a, b), add(hr, b, a);
        }
    }
    start = id[1];
    ans = f[start] = sz[start];
    for (int u = start; u; u--) {
        for (int i = hs[u]; i; i = nxt[i]) {
            int j = e[i];
            f[j] = max(f[j], f[u] + sz[j]);
        }
    }
    for (int u = start; u <= scc; ++u) {
        for (int i = hr[u]; i; i = nxt[i]) {
            int j = e[i];
            f[j] = max(f[j], f[u] + sz[j]);
        }
        for (int i = hs[u]; i; i = nxt[i]) {
            int j = e[i];
            if (j <= start)
                ans = max(ans, f[j] + f[u] - sz[start]);
        }
        
    }
    
    cout << ans;
}
2024/5/23 16:06
加载中...