欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

相关标签: 图论