电力
给定一个由 n 个点 m 条边构成的无向图,请你求出该图删除一个点之后,连通块最多有多少。
输入格式
输入包含多组数据。
每组数据第一行包含两个整数 n,m。
接下来 m 行,每行包含两个整数 a,b,表示 a,b 两点之间有边连接。
数据保证无重边。
点的编号从 0 到 n−1。
读入以一行 0 0 结束。
输出格式
每组数据输出一个结果,占一行,表示连通块的最大数量。
数据范围
1
≤
n
≤
10000
1≤n≤10000
1≤n≤10000,
0
≤
m
≤
15000
0≤m≤15000
0≤m≤15000,
0
≤
a
,
b
<
n
0≤a,b<n
0≤a,b<n
输入样例:
3 3
0 1
0 2
2 1
4 2
0 1
2 3
3 1
1 0
0 0
输出样例:
1
2
2
题解:
这道题显然是无向图求割点的题目。我们需要注意的就是我们枚举删点的时候如果这个点不是根,那么删掉他我们多了两个区域,一个是他子孙的联通快,一个就是他父亲节点那个联通块。所以需要特判一下。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int ne[N],head[N],e[N],dfn[N],low[N],is_bridge[N],in_st[N];
stack<int> st;
int root;
int d[N],cnt,n,m,timetamp,d_scc,id[N],ans,res;
void add(int a,int b)
{
e[cnt]=b,ne[cnt]=head[a],head[a]=cnt++;
}
void tarjan(int u)
{
int con=0;
low[u]=dfn[u]=++timetamp;
for(int i=head[u];~i;i=ne[i]){
int j=e[i];
if(!dfn[j]){
tarjan(j);
low[u]=min(low[u],low[j]);
if(low[j]>=dfn[u]) con++;
}else low[u]=min(low[u],dfn[j]);
}
if(u!=root&&con) con++;
res=max(res,con);
}
int main()
{
while((cin>>n>>m),n||m){
cnt=0;
timetamp=0;
res=0;
memset(dfn,0,sizeof dfn);
memset(low,0,sizeof low);
memset(head,-1,sizeof head);
for(int i=1;i<=m;i++){
int a,b; cin>>a>>b;
add(a,b),add(b,a);
}
int liantong=0;
for(root=0;root<n;root++)
if(!dfn[root]) liantong++,tarjan(root);
cout<<res+liantong-1<<endl;
}
}