点双通分量

发布时间 2023-12-06 21:29:44作者: 卡布叻_周深
#include<bits/stdc++.h>
#define int long long 
#define endl '\n'
using namespace std;
const int N=5e5+1; 
vector<int>e[N],dcc[N];
int dfn[N],low[N],a,b,n,m,tot,num;
stack<int>s;
template<typename Tp> inline void read(Tp&x)
{
    x=0;register bool f=1;
    register char c=getchar();
    for(;c<'0'||c>'9';c=getchar()) if(c=='-') f=0;
    for(;'0'<=c&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    x=(f?x:~x+1);
}
void tarjan(int x,int fa)
{
	dfn[x]=low[x]=++tot;
	s.push(x);
	if(x==fa&&e[x].size()==0)
	{
		dcc[++num].push_back(x);
		return ;
	}
	for(int y:e[x])
		if(!dfn[y])
		{
			tarjan(y,fa);
			low[x]=min(low[x],low[y]);
			if(low[y]>=dfn[x])
			{
				++num;
				int z;
				while(z!=y)
					z=s.top(),
					s.pop(),
					dcc[num].push_back(z);
				dcc[num].push_back(x);
			}
		}
		else low[x]=min(low[x],dfn[y]);
}
signed main()
{
	#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
	read(n),read(m);
	while(m--)
		read(a),read(b),
		e[a].push_back(b),
		e[b].push_back(a);
	for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,i);
	cout<<num<<endl;
	for(int i=1;i<=num;i++)
	{
		cout<<dcc[i].size()<<' ';
		for(int j=0;j<dcc[i].size();j++)
			cout<<dcc[i][j]<<' ';
		cout<<endl;
	}
}