http://acm.hdu.edu.cn/showproblem.php?pid=4587

4 5 0 1 1 2 2 3 3 0 0 2
2
/**
hdu4587 求割点变形
题目大意:给定一个图,去掉其中哪两点后能得到最多的连通块,是多少
解题思路:枚举去掉第一个点,然后利用求割点的模板就可以求出去掉另一点后的答案,取最多即可
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=5010;
struct note
{
int v,next;
bool cut;
} edge[maxn*2];
int head[maxn],ip;
void init()
{
memset(head,-1,sizeof(head));
ip=0;
}
int low[maxn],dfn[maxn],st[maxn],dex,top;
bool inst[maxn],cut[maxn];
int add_block[maxn];
int bridge;
int n,m,now;
void addedge(int u,int v)
{
edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;
}
void tarjan(int u,int pre)
{
low[u]=dfn[u]=++dex;
st[top++]=u;
inst[u]=true;
int son=0;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].v;
if(v==pre)continue;
if(v==now)continue;
if(!dfn[v])
{
son++;
tarjan(v,u);
if(low[u]>low[v])low[u]=low[v];
if(low[v]>dfn[u])
{
bridge++;
edge[i].cut=true;
edge[i^1].cut=true;
}
if(u!=pre&&low[v]>=dfn[u])
{
cut[u]=true;
add_block[u]++;
}
}
else if(low[u]>dfn[v])
{
low[u]=dfn[v];
}
}
if(u==pre&&son>1)cut[u]=true;
if(u==pre)add_block[u]=son-1;
inst[u]=false;
top--;
}
int solve()
{
memset(dfn,0,sizeof(dfn));
memset(inst,false,sizeof(inst));
memset(add_block,0,sizeof(add_block));
memset(cut,false,sizeof(cut));
dex=top=0;
bridge=0;
int cnt=0;
for(int i=0;i<n;i++)
{
if(i!=now&&!dfn[i])
{
cnt++;
tarjan(i,i);
}
}
int ans=-1;
for(int i=0;i<n;i++)
{
if(i!=now)
{
ans=max(ans,cnt+add_block[i]);
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
int ans=-1;
for(int i=0;i<n;i++)
{
now=i;
ans=max(ans,solve());
}
printf("%d\n",ans);
}
return 0;
}
原文:http://blog.csdn.net/lvshubao1314/article/details/44025035