只有当一个顶点是割点的时候,删掉这个点才可以增加图中连通块的个数
在(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;
}