AcWing 1183. 电力(无向图的双连通分量)
程序员文章站
2022-07-01 17:27:28
题目给定一个由 n 个点 m 条边构成的无向图,请你求出该图删除一个点之后,连通块最多有多少。输入格式输入包含多组数据。每组数据第一行包含两个整数 n,m。接下来 m 行,每行包含两个整数 a,b,表示 a,b 两点之间有边连接。数据保证无重边。点的编号从 0 到 n−1。读入以一行 0 0 结束。输出格式每组数据输出一个结果,占一行,表示连通块的最大数量。数据范围1≤n≤10000,0≤m≤15000,0≤a,b
题目
给定一个由 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;
}
本文地址:https://blog.csdn.net/qq_44828887/article/details/107367802
上一篇: 古人制造鞋子的时候,鞋尖为什么是上翘的?
下一篇: 针灸的历史起源