Wa13求调
查看原帖
Wa13求调
533665
lefthand166楼主2024/11/21 17:37

初学tarjan求调

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
vector<int> child[maxn];
int dfn[maxn];
int dfsclock;
bool iscut[maxn];
vector<int> scc[maxn];
int cnt;
bool vis[maxn];
int c[maxn];
int siz[maxn];
int s[maxn];
set<int> to[maxn];
set<int> con;
vector<int> buff;
int tarjan(int pa, int p) {
    int lowp = dfn[p] = ++dfsclock;
    int chi = 0;
    buff.push_back(p);
    for (int u : child[p]) {
        if (!dfn[u]) {
            chi++;
            int lowu = tarjan(p, u);
            lowp = min(lowp, lowu);
            if (lowu >= dfn[p]) 
                iscut[p] = 1;
        } else if (dfn[u] < dfn[p] && u != pa) 
            lowp = min(lowp, dfn[u]);
    }
    if (lowp == dfn[p]) {
        cnt++;
        int y;
        do {
            y = buff.back();
            scc[cnt].push_back(y);
            c[y] = cnt;
            buff.pop_back();
        } while (y != p);
    }
    if (pa == 0 && chi == 1) iscut[p] = 0;
    return lowp;
}
int fa[maxn];
void dfs(int pa, int p) {
    fa[p] = pa;
    s[p] = siz[p];
    for (int u : to[p]) {
        if (u == pa) continue;
        dfs(p, u);
        s[p] += s[u];
    }
}
int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        child[u].push_back(v);
        child[v].push_back(u);
    }
    tarjan(0, 1);
    for (int i = 1; i <= cnt; i++) 
        for (int u : scc[i]) {
            siz[i]++;
            for (int v : child[u]) 
                if (c[v] != i)
                    to[i].insert(c[v]);
        }
    dfs(0, 1);
    for (int i = 1; i <= n; i++) {
        if (!iscut[i]) {
            cout << (n - 1) * 2 << "\n";
        } else {
            long long ans = 0, sum = 0;
            con.clear();
            for (int u : child[i]) con.insert(c[u]);
            con.erase(c[i]);
            for (int u : con) {
                if (fa[c[i]] == u) {
                    ans += sum * (s[1] - s[c[i]]);
                    sum += s[1] - s[c[i]];
                } else {
                    ans += sum * s[u];
                    sum += s[u];    
                }
            }
            cout << (ans + sum * (s[1] - sum - 1) + (n - 1)) * 2 << "\n";
        }
    }
}
2024/11/21 17:37
加载中...