题目大意:给一个图,删除两个不同的点,求剩下的连通块数量的可能的最大值。
思路:枚举第一个删除的点,用sum[i]表示删除i点增加的连通块的数目。而具体sum[i]怎么求?如果熟悉割点的求法的话,这个是很简单的。
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
//typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF=100011122;
const double INFF=1e100;
const double eps=1e-8;
const int mod=9999991;
const int NN=5005;
const int MM=5010;
/* ****************** */
struct G
{
int v,next;
}E[NN*2];
int p[NN],T;
int dfn[NN],low[NN],tsp;
int del;
int sum[NN];
void add(int u,int v)
{
E[T].v=v;
E[T].next=p[u];
p[u]=T++;
}
void tarjan(int u,int fa)
{
int i,v,son=0;
dfn[u]=low[u]=++tsp;
for(i=p[u];i+1;i=E[i].next)
{
v=E[i].v;
if(v==fa || v==del)continue;
if(dfn[v]==0)
{
son++;
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
sum[u]++;
}
}
else
low[u]=min(low[u],dfn[v]);
}
if(fa==-1)sum[u]--;
}
int main()
{
int n,m;
int i,j,u,v,block,ans;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(p,-1,sizeof(p));
T=0;
while(m--)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
ans=0;
for(i=0;i<n;i++)
{
del=i;
for(j=0;j<n;j++)
{
dfn[j]=low[j]=0;
sum[j]=0;
}
tsp=0;
block=0;
for(j=0;j<n;j++)
{
if(j==del)continue;
if(dfn[j]==0)
{
tarjan(j,-1);
block++;
}
}
for(j=0;j<n;j++)
{
if(i==j)continue;
ans=max(ans,block+sum[j]);
}
}
printf("%d\n",ans);
}
return 0;
}