点/边双连通分量板子
点双
没写完
边双缩点
#include<bits/stdc++.h>
#define int long long
#define ll long long
#define fd(i,a,b) for(int i=(a);i<=(b);i=-~i)
#define bd(i,a,b) for(int i=(a);i>=(b);i=~-i)
#define db(x) cout<<"DEBUG "<<#x<<" = "<<x<<endl;
#define endl '\n'
using namespace std;
//#define SIZE (1<<20)
//char In[SIZE],Out[SIZE],*p1=In,*p2=In,*p3=Out;
//#define getchar() (p1==p2&&(p2=(p1=In)+fread(In,1,SIZE,stdin),p1==p2)?EOF:*p1++)
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();}
return x*f;
}
template<typename _T>
inline void write(_T x)
{
static _T sta[35];int top=0;
if(x<0) putchar('-'),x=-x;
do{sta[top++]=x%10,x/=10;}while(x);
while(top) putchar(sta[--top]+'0');
}
const int N=2e5+509,M=1e6+509,mod=998244353;
int n,m;
struct edge{int y,z,id;};
vector<edge> e[N];
vector<edge> bri;
int idx,dfn[N],low[N];
stack<int> sta;
int c[N],sccsum;
vector<int> scc[N];
void tarjan(int x,int fa)
{
dfn[x]=low[x]=++idx;
sta.push(x);
for(auto &[y,z,id]:e[x])
{
if(id==fa) continue;
if(!dfn[y])
{
tarjan(y,id);
low[x]=min(low[x],low[y]);
}
else low[x]=min(low[x],dfn[y]);
}
if(dfn[x]==low[x])
{
int y;++sccsum;
do
{
y=sta.top();sta.pop();
scc[sccsum].push_back(y);
c[y]=sccsum;
}while(y!=x);
}
}
vector<edge> g[N];
void build()
{
fd(x,1,n)
{
for(auto &[y,z,id]:e[x])
if(c[x]!=c[y])
g[c[x]].push_back({c[y],z,id}),
bri.push_back({x,y,id});
}
}
signed main()
{
//#define FJ
#ifdef FJ
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#else
// freopen("A.in","r",stdin);
// freopen("A.out","w",stdout);
#endif
//#define io
#ifdef io
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
#endif
n=read(),m=read();
fd(i,1,m)
{
int x=read(),y=read();
e[x].push_back({y,1,i});
e[y].push_back({x,1,i});
}
fd(i,1,n) if(!dfn[i]) tarjan(i,0);
build();
return 0;
}
本文来自博客园,作者:whrwlx,转载请注明原文链接:https://www.cnblogs.com/whrwlx/p/18573566