求助有赏85ptsRE——关于以缩点栈形式Tarjan求边双
查看原帖
求助有赏85ptsRE——关于以缩点栈形式Tarjan求边双
444040
Echoternity楼主2022/12/6 22:15

在与同机房巨佬谈边双的时候,觉得写第二遍 dfs 有点麻烦了,就想能不能用栈的形式(也就是缩点那种形式)求出边双,然后胡了一下,发现可做,然后RE 85pts,下数据发现该方法似乎不能处理自环和重边。

求助万能的谷友,这个方法能不能改进,悬赏两个关注。

给代码:

// ----- Eternally question-----
// Problem: P8436 【模板】边双连通分量
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P8436
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// Written by: Eternity
// Time: 2022-12-06 21:43:48
// ----- Endless solution-------

#include<bits/stdc++.h>
#define re register
typedef long long ll;
template<class T>
inline void read(T &x)
{
	x=0;
	char ch=getchar(),t=0;
	while(ch<'0'||ch>'9') t|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	if(t) x=-x;
}
template<class T,class ...T1>
inline void read(T &x,T1 &...x1){ read(x),read(x1...); }
template<class T>
inline void write(T x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
}
template<>
inline void write(bool x){ putchar(x?'1':'0'); }
template<>
inline void write(char c){ putchar(c); }
template<>
inline void write(char *s){ while(*s!='\0') putchar(*s++); }
template<>
inline void write(const char *s){ while(*s!='\0') putchar(*s++); }
template<class T,class ...T1>
inline void write(T x,T1 ...x1){ write(x),write(x1...); }
template<class T>
inline bool checkMax(T &x,T y){ return x<y?x=y,1:0; }
template<class T>
inline bool checkMin(T &x,T y){ return x>y?x=y,1:0; }
const int MAXN=5e5+10,MAXM=2e6+10;
int N,M;
struct G
{
	int next,to;
}Edge[MAXM<<1];
int Head[MAXN],Total;
inline void addEdge(int u,int v)
{
	Edge[++Total]=(G){Head[u],v};Head[u]=Total;
	Edge[++Total]=(G){Head[v],u};Head[v]=Total;
}
int Dfn[MAXN],Low[MAXN],Stk[MAXN],Cnt,Top;
bool Ins[MAXN];
int Dcc[MAXN],Sizc[MAXN],Dc;
void Tarjan(int x,int last)
{
	Dfn[x]=Low[x]=++Cnt,Ins[x]=1,Stk[++Top]=x;
	for(int e=Head[x],v;e;e=Edge[e].next)
	{
		if((v=Edge[e].to)==last) continue;
		if(!Dfn[v])
		{
			Tarjan(v,x);
			checkMin(Low[x],Low[v]);
		}
		else if(Ins[v]) checkMin(Low[x],Dfn[v]);
		if(Low[v]>Dfn[x])
		{
			// write("bridge:",x,' ',v,"\nnow stack:");
			// for(int i=1;i<=Top;++i) write(Stk[i],' ');
			// puts("");
			++Dc;
			while(Stk[Top]!=v)
			{
				Dcc[Stk[Top]]=Dc,++Sizc[Dc];
				Ins[Stk[Top]]=0,--Top;
			}
			Dcc[v]=Dc,++Sizc[Dc],Ins[v]=0,--Top;
		}
	}
}
std::vector<int>Scc[MAXN];
int main()
{
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
	read(N,M);
	for(int i=1,u,v;i<=M;++i){ read(u,v);addEdge(u,v); }
	for(int x=1;x<=N;++x) if(!Dfn[x])
	{
		Tarjan(x,0);
		if(Top)
		{
			++Dc;
			while(Top)
			{
				Dcc[Stk[Top]]=Dc,++Sizc[Dc];
				Ins[Stk[Top]]=0,--Top;
			}
		}
	}
	for(int i=1;i<=N;++i) Scc[Dcc[i]].push_back(i);
	write(Dc,'\n');
	for(int i=1;i<=Dc;++i,puts(""))
	{
		write(Scc[i].size(),' ');
		for(int x:Scc[i]) write(x,' ');
	}
	return 0;
}
/*

*/
2022/12/6 22:15
加载中...