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;
}