枚举去掉一个点,再用一个tarjan 求出去掉第二个点最多能分成多少块?
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=5e3+5;
int n,m,idx;
int l[maxn],r[maxn];
int dfn[maxn],low[maxn],sub[maxn];
int root,chd;
vector<int>G[maxn];
inline void dfs(int u,int fa){
low[u]=dfn[u]=++idx;
for(int i=0;i<G[u].size();++i){
int v=G[u][i];
if(!dfn[v]){
dfs(v,u);
low[u]=min(low[u],low[v]);
if(u==root)++chd;
else if(low[v]>=dfn[u])++sub[u];
}else if(v!=fa)low[u]=min(low[u],dfn[v]);
}
}
inline int work(int tar){
for(int i=0;i<n;++i)G[i].clear();
for(int i=0;i<m;++i)
if(l[i]!=tar&&r[i]!=tar){
G[l[i]].push_back(r[i]);
G[r[i]].push_back(l[i]);
}
memset(dfn,0,sizeof(int)*n);
memset(low,0,sizeof(int)*n);
memset(sub,0,sizeof(int)*n);
int cnt=0;
for(int i=0;i<n;++i)
if(!dfn[i]){
++cnt;
idx=0;
root=i;chd=0;
dfs(i,-1);
sub[i]=chd-1;
}
cnt--;
//cout<<cnt<<endl;
int res=0;
for(int i=0;i<n;++i)res=max(res,cnt+sub[i]);
res=max(res,0);
return res;
}
int main()
{
// freopen("T.in","r",stdin);
// freopen("T.out","w",stdout);
while(~scanf("%d%d",&n,&m)){
for(int i=0;i<m;++i){
scanf("%d%d",l+i,r+i);
}
int ans=0;
for(int i=0;i<n;++i)
ans=max(ans,work(i));
printf("%d\n",ans);
}
return 0;
}