莫欺少年穷,修魔之旅在这开始—>算法提高课题解
思路:
1. 计算出所有连通块个数 cnt
2. 枚举所有连通块
3. 枚举把这个连通块中的点删除后得到的连通块个数
4. 用全局变量 ans 记录删除某点后得到的连通块个数的最大值
5. 如果这个点不是根节点,则连通块个数还要算上他的父节点
6. 最终答案:ans + cnt - 1
#include<bits/stdc++.h>
using namespace std;
const int N = 10010, M = 30010;
int n,m;
int h[N],e[M],ne[M],idx;
int dfn[N],low[N],timestamp;
int root,ans;
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void tarjan(int u)
{
dfn[u]=low[u]=++timestamp;
//记录把这个点删除后得到的连通块个数
int cnt=0;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(!dfn[j])
{
tarjan(j);
low[u]=min(low[u],low[j]);
//表示把该点删除后会多一个连通块
if(dfn[u]<=low[j]) cnt++;
}
else low[u]=min(low[u],dfn[j]);
}
//不是根节点
if(u!=root) cnt++;
//记录所有把某个点删除后,其所在连通块得到的新的连痛快的最大个数
ans=max(ans,cnt);
}
int main()
{
while(cin>>n>>m,n||m)
{
//初始化
idx=0;
memset(h,-1,sizeof h);
memset(dfn,0,sizeof dfn);
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
//枚举所有点
ans=0;
int cnt=0;
for(root=0;root<n;root++)
if(!dfn[root])
{
//记录连通块个数
cnt++;
tarjan(root);
}
cout<<ans+cnt-1<<endl;
}
return 0;
}