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;
}
posted @ 2020-09-08 00:20  fxq1304  阅读(231)  评论(0编辑  收藏  举报