P8435 【模板】点双连通分量

      ~~~~~      P8435 【模板】点双连通分量       ~~~~~      总题单链接

      ~~~~~      建议看完割点后食用。

思路

      ~~~~~      什么是点双连通分量?就是不包含割点的极大连通块。

      ~~~~~      我们对割点要裂点,有多少个点双连通分量包含了它,它就要裂成几个点。

      ~~~~~      怎么找点双连通分量?就是割点的时候将遍历到的点放到一个桶里,在遍历 u u u 的邻点 v v v 时,若 v v v 的时间戳 ≥ \geq u u u 的时间戳,那当前桶内的点和 u u u 就是一个点双连通分量。

模版题代码

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

ll n,m,tot,cnt,stk[500005];
ll dfn[500005],low[500005],top;
vector<ll>eg[500005],scc[500005];

void Tarjan(ll p){
	if(eg[p].empty()){
		scc[++cnt].push_back(p);
		return;
	}
	ll cld=0;
	stk[++top]=p;
	dfn[p]=low[p]=++tot;
	for(ll v:eg[p]){
		if(!dfn[v]){
			Tarjan(v);
			low[p]=min(low[p],low[v]);
			if(low[v]>=dfn[p]){
				cnt++;
				while(1){
					ll z=stk[top--];
					scc[cnt].push_back(z);
					if(z==v)break;
				}
				scc[cnt].push_back(p);
			}
		}
		else low[p]=min(low[p],dfn[v]);
	}
}

signed main(){
	ios::sync_with_stdio(false);
	
	cin>>n>>m;
	while(m--){
		ll x,y;cin>>x>>y;
		if(x==y)continue;
		eg[x].push_back(y);
		eg[y].push_back(x);
	}
	
	for(ll i=1;i<=n;i++)
		if(!dfn[i])Tarjan(i);
	
	cout<<cnt<<endl;
	for(ll i=1;i<=cnt;i++){
		cout<<scc[i].size()<<" ";
		for(ll it:scc[i])cout<<it<<" ";
		cout<<endl;
	}
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值