*割点割桥

#include<bits/stdc++.h>
using namespace std;

const int maxn=20005;
struct dot {
	int cd,next[maxn],child;
}a[maxn];
int n,m,sum,tim[maxn],low[maxn],t;
int fa[maxn];
bool tip[maxn];

int minn(int x,int y) {
	if(x <= y) return x;
	else return y;
}

void dfs(int z) {
	t++;
	tim[z]=low[z]=t;
	if(a[z].cd != 0) {
		for(int i=1;i<=a[z].cd;i++) {
			if(tim[a[z].next[i]] == 0) {
				a[z].child++; //记录搜索树上的子节点数
				fa[a[z].next[i]]=z;
				dfs(a[z].next[i]);
				if(fa[z] == 0 && a[z].child >= 2 && tip[z] != true) {
					tip[z]=true;
					sum++;//根节点为割点的判定
				}
				if(fa[z] != 0 && low[a[z].next[i]] >= tim[z] && tip[z] != true) {
					tip[z]=true;
					sum++;//非根节点为割点的判定
				}
				/*
				if(low[a[z].next[i]] > tim[i]),则 x->y为桥 
				*/
				low[z]=minn(low[z],low[a[z].next[i]]);//low的维护
			}
			else if(a[z].next[i] != fa[z]) {
				low[z]=minn(low[z],tim[a[z].next[i]]);
                //这里用tim是因为a[z].next[i]的low可能是令一个非树边联通的,也就是说会导致z的low变成经过两次非树边结果,与low的定义违背,见如下数据样例
			}
		}
	}
} 

int main() {
	cin>>n>>m;
	for(int i=1;i<=m;i++) {
		int x,y;
		cin>>x>>y;
		a[x].cd++;
		a[x].next[a[x].cd]=y;
		a[y].cd++;
		a[y].next[a[y].cd]=x;
	}//无向图的构建
	for(int i=1;i<=n;i++) {
		if(tim[i] == 0) dfs(i);
	}
	cout<<sum<<endl;
	for(int i=1;i<=n;i++) {
		if(tip[i] == true) cout<<i<<" ";
	} 
	return 0;
}
/*
5 6
1 2
1 3
2 3
3 4
3 5
4 5
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值