mountain_climber @ 2024-10-21 14:26:59
可能会有重边。
如果写Vector可以考虑使用以下方法:
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
inline int read(){
char ch=getchar();int x=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void write(int x){
if(x<0){x=~(x-1);putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
int n,m;
int dfn[N],low[N],dfncnt=0,fatr[N];
bool flg[N]={false},flg1[N]={false};
int edcc[N],tot=0;//edcc表示i所处的边双的编号,tot表示一共有多少个边双
vector<int> g[N],ans[N];
vector<int> id[N];
inline void tarjan(int u,int fa,int idx){
dfn[u]=low[u]=++dfncnt;
fatr[u]=fa;
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if(!dfn[v]){
tarjan(v,u,id[u][i]);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]){
flg[v]=true;
flg1[v]=true;
}
}
else if(dfn[v]&&(v!=fa||i!=idx)){
low[u]=min(low[u],dfn[v]);
}
}
}
inline void dfs(int now){
edcc[now]=tot;
ans[tot].push_back(now);
for(auto v:g[now]){
if(((fatr[now]==v&&flg[now])||(fatr[v]==now&&flg[v]))||edcc[v]){
continue;
}
dfs(v);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL),cout.tie(NULL);
n=read(),m=read();
for(int i=1;i<=m;i++){
int u,v;
u=read(),v=read();
g[u].push_back(v);
g[v].push_back(u);
id[u].push_back(g[v].size()-1);
id[v].push_back(g[u].size()-1);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i,i,-1);
}
}
for(int i=1;i<=n;i++){
if(!edcc[i]){
// cout<<'!'<<i<<'\n';
++tot;
dfs(i);
}
}
// for(int i=1;i<=n;i++){
// if(flg1[i]){
// cout<<fatr[i]<<'-'<<i<<'\n';
// }
// }
write(tot);puts("");
for(int i=1;i<=tot;i++){
write(ans[i].size());printf(" ");
for(auto j:ans[i]){
write(j);printf(" ");
}
puts("");
}
return 0;
}
//100pts,神秘id记录法直接不带log
本质上是把重边的节点重复跑,从而让其无法成为割边。