求点双联通分量(HihoCoder - 1190 )
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
struct my{
int v;
int next;
int id;
};
my bian[2000000+10];
int adj[200000+10];
int maxn=(1<<29);
int sccno[200000+10];
int belong[200000+10];
int pre[200000+10];
int bccnum;
int dfsnum;
int fa1;
int n,m;
stack<int>q;
void myinsert(int u,int v,int id){
bian[++fa1].v=v;
bian[fa1].next=adj[u];
adj[u]=fa1;
bian[fa1].id=id;
}
int tarjan(int u,int fa){
int lowu=pre[u]=++dfsnum;
for (int i=adj[u];i!=-1;i=bian[i].next){
int v=bian[i].v;
int e=bian[i].id;
if(belong[e]) continue;
if(!pre[v]){
q.push(e);
int lowv=tarjan(v,u);
lowu=min(lowv,lowu);
if(lowv>=pre[u]){
bccnum++;
int no=maxn;
for (;;){
int e2=q.top();
q.pop();
belong[e2]=bccnum;
no=min(no,e2);
if(e2==e||q.empty()) break;
}
sccno[bccnum]=no;
}
} else if(v!=fa&&pre[v]<pre[u]){
q.push(e);
lowu=min(lowu,pre[v]);
}
}
return lowu;
}
int main(){
memset(bian,-1,sizeof(bian));
memset(adj,-1,sizeof(adj));
scanf("%d%d",&n,&m);
int u,v;
for (int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
myinsert(u,v,i);
myinsert(v,u,i);
}
/*for (int i=1;i<=n;i++){
printf("%d ",i);
for (int j=adj[i];j!=-1;j=bian[j].next){
printf("%d ",bian[j].v);
}
printf("\n");
}*/
tarjan(1,-1);
printf("%d\n",bccnum);
for (int i=1;i<=m;i++){
int id=belong[i];
printf("%d ",sccno[id]);
}
printf("\n");
return 0;
}