题意:给你n个点,m条边,要你删除两个点以及和这两个点直接相连的边,问你剩下的图中,最大的连通分量的数目。
分析:我们可以枚举每个点,然后看剩下的图中是否有割点,这里需要注意,一个单独的连通分量删除就没有了,坑点在这里!!!
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <vector>
#include <stack>
using namespace std;
const int maxn=5005;
const int maxm=1000005;
struct EdgeNode
{
int from;
int to;
int bj;
int next;
}edge[maxm];
int head[maxn],cnt,flag;
int dfn[maxn],low[maxn],cixu,n,gds[maxn];
void add(int x,int y)
{
edge[cnt].from=x;
edge[cnt].to=y;
edge[cnt].bj=1;
edge[cnt].next=head[x];
head[x]=cnt++;
}
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
void dfs(int u,int fa)
{
int v,child=0;
dfn[u]=low[u]=++cixu;
for(int i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(edge[i].bj==0)continue;
if(!dfn[v])
{
dfs(v,u);
child++;
low[u]=min(low[u],low[v]);
if((fa==-1&&child>1)||(fa!=-1&&low[v]>=dfn[u]))
{
gds[u]++; //删除u点后增加的连通分量数目
}
}
else if(v!=fa)
low[u]=min(low[u],dfn[v]);
}
}
int tarjan()
{
int sum=-1;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
cixu=0;
for(int i=1;i<=n;i++)
{
if(!dfn[i]){
dfs(i,-1);
sum++;
}
}
int mn=-1;
if(sum==n-1)sum--;
for(int i=1;i<=n;i++)mn=max(mn,gds[i]);
sum+=mn;
return sum;
}
int main()
{
int i,j,x,y,m,chu;
while(~scanf("%d%d",&n,&m))
{
init(); chu=-1;
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
x++; y++;
add(x,y);
add(y,x);
}
for(i=1;i<=n;i++){
for(j=0;j<cnt;j++){
edge[j].bj=1;
if(edge[j].from==i||edge[j].to==i)edge[j].bj=0;
}
memset(gds,0,sizeof(gds));
chu=max(chu,tarjan());
}
printf("%d\n",chu);
}
return 0;
}