hdu4587 无向图删掉两个顶点之后连通块的最大个数
hdu4587 TWO NODES
传送门
题意
有一个\(n(3\leq n\leq 5000)\)个点,\(m(3\leq m\leq 5000)\)条边的无向图,删去任意两个顶点以及所有与它们相关的边,计算剩下的图的连通块的最大个数
题解
枚举删去的顶点,tarjan算法计算剩下的图的最大联通块个数,更新结果
#include<iostream>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<sstream>
#include<cmath>
#include<ctime>
#include<climits>
#include<algorithm>
#define LL long long
#define PII pair<int,int>
#define PLL pair<LL,LL>
#define pi acos(-1.0)
#define eps 1e-6
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=5010,maxm=10010;
int n,m,sum1,sum2,aim;
int head[maxn],nxt[maxm],to[maxm],cnt;
int dfn[maxn],low[maxn],dfscnt;
void add(int u,int v){
to[cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt++;
}
void init(int u){
sum1=0;
sum2=-1;
memset(dfn,0,sizeof(dfn));
dfscnt=0;
aim=u;
}
void tarjan(int u,int fa){
dfn[u]=low[u]=++dfscnt;
int child=0,cur=0;
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
if(v==aim) continue;
if(!dfn[v]){
child++;
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]) cur++;
}
else if(v!=fa){
low[u]=min(low[u],dfn[v]);
}
}
if(fa==-1) sum2=max(sum2,cur-1);
else sum2=max(sum2,cur);
}
int main(){
while(~scanf("%d%d",&n,&m)){
memset(head,-1,sizeof(head));
cnt=0;
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
int ans=0;
for(int i=0;i<n;i++){
init(i);
for(int j=0;j<n;j++){
if(j==i) continue;
if(!dfn[j]){
sum1++;
tarjan(j,-1);
}
}
sum1+=sum2;
ans=max(ans,sum1);
}
printf("%d\n",ans);
}
return 0;
}