题意:n点的无向图,问删除两个点以后,该图最多被分成多少个联通快?
题解:枚举删除的第一个点,对于剩下的图如果存在割点,那么删除的那个点一定是割点。同时在求割点的过程中,我们可以处理出删除这个割点可以把原来的联通快分成了几块。那么这个题就可以解决了。复杂度O(n^2)
详情见代码:
#include
#include
#include
#include
#define nn 5100
using namespace std;
typedef __int64 LL;
int n,m;
struct node
{
int st,en,next;
}E[nn*2];
int p[nn],num;
void init()
{
memset(p,-1,sizeof(p));
num=0;
}
void add(int st,int en)
{
E[num].en=en;
E[num].next=p[st];
p[st]=num++;
}
bool use[nn];
int dfn[nn],low[nn],df;
int dp[nn];
void dfs(int id,int fa,int gen)
{
dfn[id]=low[id]=++df;
dp[id]=1;
int son=0;
int i,w;
for(i=p[id];i+1;i=E[i].next)
{
w=E[i].en;
if(use[w]||w==fa)
continue;
if(dfn[w]==-1)
{
if(id==gen)
son++;
dfs(w,id,gen);
low[id]=min(low[id],low[w]);
if(low[w]>=dfn[id]&&id!=gen)
{
dp[id]++;//统计该割点可以把原来的联通快分成几块
}
}
else
{
low[id]=min(low[id],dfn[w]);
}
}
if(id==gen)
{
dp[id]=son;//统计根节点可以把原来的联通快分成几块
}
}
int main()
{
int i,j;
int u,v;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
memset(use,false,sizeof(use));
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
u++,v++;
add(u,v);
add(v,u);
}
int ans=0;
for(i=1;i<=n;i++)
{
use[i]=true;
memset(dfn,-1,sizeof(dfn));
df=0;
int ix=0;
for(j=1;j<=n;j++)
{
if(!use[j]&&dfn[j]==-1)
{
ix++;
dfs(j,j,j);
}
}
for(j=1;j<=n;j++)
{
if(use[j])
continue;
ans=max(ans,ix-1+dp[j]);
}
use[i]=false;
}
printf("%d\n",ans);
}
return 0;
}