Loading

POJ-2117 Electricity

Electricity

计算割去某个点后,最大的连通块数量

tarjan 割点

跑一次 \(tarjan\) 记录一下每个点删去后会产生多少个新的连通块,相当于找 \(low[nex] \ge dfn[now]\) 的数量

如果为根节点,那么多出来的连通块数量要减一,因为本身没有父节点方向的连通块

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1e4 + 10;
int head[maxn], nexx[maxn * 100], to[maxn * 100], vp = 0;
int low[maxn], dfn[maxn], tp = 0;
int cnt[maxn];

inline void add(int u, int v)
{
    vp++;
    nexx[vp] = head[u];
    to[vp] = v;
    head[u] = vp;
}

void tarjan(int now, int x)
{
    low[now] = dfn[now] = ++tp;
    int ans = 0;
    for(int i=head[now]; i; i=nexx[i])
    {
        int nex = to[i];
        if(dfn[nex] == 0)
        {
            tarjan(nex, 0);
            low[now] = min(low[now], low[nex]);
            if(low[nex] >= dfn[now])
                ans++;
        }
        else
            low[now] = min(dfn[nex], low[now]);
    }
    if(x) cnt[now] = ans - 1;
    else cnt[now] = ans;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m;
    while(cin >> n >> m && (n || m))
    {
        vp = tp = 0;
        for(int i=0; i<n; i++) dfn[i] = low[i] = head[i] = 0;
        while(m--)
        {
            int a, b;
            cin >> a >> b;
            add(a, b);
            add(b, a);
        }
        int sum = 0, ans = 0;
        for(int i=0; i<n; i++)
        {
            if(dfn[i] == 0)
            {
                sum++;
                tarjan(i, 1);
            }
        }
        for(int i=0; i<n; i++)
            ans = max(ans, sum + cnt[i]);
        cout << ans << "\n";
    }
    return 0;
}
posted @ 2022-08-25 22:59  dgsvygd  阅读(22)  评论(0编辑  收藏  举报