当前位置: 代码迷 >> 综合 >> AcWing 1183. 电力(无向图的双连通分量)
  详细解决方案

AcWing 1183. 电力(无向图的双连通分量)

热度:95   发布时间:2024-01-28 15:29:26.0

题目

给定一个由 n 个点 m 条边构成的无向图,请你求出该图删除一个点之后,连通块最多有多少。

输入格式

输入包含多组数据。

每组数据第一行包含两个整数 n,m。

接下来 m 行,每行包含两个整数 a,b,表示 a,b 两点之间有边连接。

数据保证无重边。

点的编号从 0 到 n?1。

读入以一行 0 0 结束。

输出格式

每组数据输出一个结果,占一行,表示连通块的最大数量。

数据范围

1≤n≤10000,
0≤m≤15000,
0≤a,b<n

思路

求割点,如果没有割点那答案就是连通块的个数,否则,就是删去割点后连通块的个数。我们需要用个数组存一下删除此点后可以加的连通块的个数。如果不是根节点那么就要加1.

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;const int N=1e4+7,M=6e4+7; int n,m;
int h[N],e[M],ne[M],idx;
int dfn[N],low[N],timestamp;
int ans,root;void add(int a,int b)
{e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}void tarjan(int u)
{dfn[u]=low[u]=++timestamp;int cnt=0;for(int i=h[u];~i;i=ne[i]){int j=e[i];if(!dfn[j]){tarjan(j);low[u]=min(low[u],low[j]);if(low[j]>=dfn[u])  cnt++;}else low[u]=min(low[u],dfn[j]);}if(u!=root) cnt++;ans=max(ans,cnt) ;
}int main()
{//freopen("test.in","r",stdin);//设置 cin scanf 这些输入流都从 test.in中读取//freopen("test.out","w",stdout);//设置 cout printf 这些输出流都输出到 test.out里面去ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);while(cin>>n>>m,(n||m)){memset(dfn,0,sizeof dfn);memset(h,-1,sizeof h);idx=timestamp=0;while(m--){int a,b;cin>>a>>b;add(a,b),add(b,a);}ans=0;int cnt=0;for(root=0;root<n;root++){if(!dfn[root]){cnt++;tarjan(root);}}cout<<ans+cnt-1<<endl;}return 0;
}