洛谷 P3388 【模板】割点(割顶) 题解

题目来源:

https://www.luogu.org/problemnew/show/P3388

题目描述:

 

题目背景

割点

题目描述

给出一个n个点,m条边的无向图,求图的割点。

输入输出格式

输入格式:

第一行输入n,m

下面m行每行输入x,y表示x到y有一条边

输出格式:

第一行输出割点个数

第二行按照节点编号从小到大输出节点,用空格隔开

输入输出样例

输入样例#1: 复制

6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6

输出样例#1: 复制

1 
5

说明

n,m均为100000

tarjan 图不一定联通!!!

解题思路:

      模板题,关键就是学习一下tarjan求割点的算法,加深一下理解,感觉现在对tarjan算法的思想有了进一步了解,但是还差点什么,以后补上。。。

代码:

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <iomanip>
const int maxn=1000005;
using namespace std;
int low[maxn],dfn[maxn],cut[maxn],tot,ans,n,m;
vector<int>E[maxn];
void tarjan(int u,int fa)
{
	int rd=0;
	low[u]=dfn[u]=++tot;
	for(int i=0;i<E[u].size();i++)
	{
		int v=E[u][i];
		if(!dfn[v]){
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u]&&u!=fa)cut[u]=1;
			if(u==fa)rd++;
		}
		low[u]=min(low[u],dfn[v]);
	}
	if(rd>=2&&u==fa)cut[fa]=1;
}
int main()
{
	std::ios::sync_with_stdio(false);
	ans=tot=0;
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int a,b;
		cin>>a>>b;
		E[a].push_back(b);
		E[b].push_back(a);
	}
	for(int i=1;i<=n;i++)
	if(!dfn[i])tarjan(i,i);
	
	for(int i=1;i<=n;i++)
	if(cut[i])ans++;
	cout<<ans<<endl;
	for(int i=1;i<=n;i++)
	if(cut[i])cout<<i<<" ";
	cout<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40400202/article/details/81197963
今日推荐