模板 无向图删掉一个顶点之后连通块的最大个数

只有当一个顶点是割点的时候,删掉这个点才可以增加图中连通块的个数
\(tarjan\)算法计算割点的过程中,对于一个顶点\(u\)
1.如果\(u\)不是根,每当出现一个子节点&v&,\(low[v]>=dfn[u]\)时,说明删掉\(u\)会使得连通块个数增加1,所以删掉\(u\)之后连通块个数的增加值为这样的\(v\)的个数
2.如果\(u\)是根,因为原先连通块的个数为\(1\),删掉\(u\)之后,连通块个数变成\(dfs\)树中子节点的个数,也就是\(child\),所以连通块个数的增加值为\((child-1)\)
设全局变量\(sum\)为删掉一个点可以增加的连通块个数的最大值,通过\(tarjan\)算法计算删掉每个点之后增加的连通块的值,更新\(sum\)
最终结果为原本的连通块个数加上\(sum\)的值
\(ps:\)由于可能存在孤立的点,删掉这些点之后增加的连通块个数为\(-1\),所以将\(sum\)的初始值设为\(-1\)

const int maxn=100010;
int dfn[maxn],low[maxn],dfscnt;
int sum;

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(!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) sum=max(sum2,cur-1);
    else sum=max(sum,cur);
}

int solve(){
    int ans=0;
    sum=-1;
    for(int i=0;i<n;i++){
        if(!dfn[i]){
            ans++;
            tarjan(i,-1);
        }
    }
    ans+=sum;
    return ans;
}
posted @ 2020-09-09 01:11  fxq1304  阅读(584)  评论(0编辑  收藏  举报