// 割边
void tar(int x,int in_e)
{
dfn[x] = low[x] = ++cnt;
for(int i=hd[0][x],y=vr[i]; i; i=nt[i],y=vr[i])
if(!dfn[y])
{
tar(y,i);
low[x] = min(low[x],low[y]);
if(low[y]>dfn[x]) bri[i]=bri[i^1]=true;
} else
if(i != (in_e^1)) low[x]=min(low[x],dfn[y]);
}
//割点
void tar(int x)
{
dfn[x] = low[x] = ++cnt;
if(rt==x && !hd[x])
{
dcc[++dcnt].clear();
dcc[dcnt].push_back(x);
return;
}
sta[++tp] = x;
for(int i=hd[x],y=vr[i]; i; i=nt[i],y=vr[i])
if(!dfn[y])
{
tar(y);
low[x] = min(low[x],low[y]);
if(low[y]>=dfn[x])
{
++flg;
if(flg>1 || x!=rt) cut[x]=true;
dcc[++dcnt].clear();
int z;
do{
z=sta[tp--];
dcc[dcnt].push_back(z);
} while(z!=y);
dcc[dcnt].push_back(x);
}
}
else low[x] = min(low[x],dfn[y]);
}
//tarjan 强连通分量
void tar(int x) {
low[x] = dfn[x] = ++dcnt;
s[++tp] = x, in_stack[x] = true;
for(int i=hd[x]; i; i=nt[i]) {
int y = vr[i];
if(!dfn[y]) {
tar(y);
low[x] = min(low[x], low[y]);
} else if(in_stack[y]) {
low[x] = min(low[x], dfn[y]);
}
}
if(dfn[x] == low[x]) {
++scnt;
while(s[tp] != x) {
scc[s[tp]] = scnt;
++siz[scnt];
in_stack[s[tp]] = false;
--tp;
}
scc[s[tp]] = scnt;
++siz[scnt];
in_stack[s[tp]] = false;
--tp;
}
}