struct ENode{
int v,w,next;
}edge[MAXM];
int p[MAXN],ec;
void InsertE(int u, int v, int w){
edge[++ec].v = v; edge[ec].w = w;
edge[ec].next = p[u];
p[u] = ec;
}
int dfn[MAXN],cTime,low[MAXN]; //时间戳,时间戳计数,祖先时间。
int gid[MAXN],gc; // 分量数组,分量计数。
bool ins[MAXN]; stack<int> sTar; //入栈标志,辅助栈
void Tarjan(int u){
dfn[u]=low[u]=++cTime; //时间戳与祖先时间初始化
ins[u]=1; sTar.push(u); //入栈
for(int i=p[u];i;i=edge[i].next){ //递归处理所有子结点
int v=edge[i].v;
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]); //利用子孙,更新能回指的祖先时间戳
}
else if(ins[v]) //记录U能回指的最早祖先的时间戳
low[u]=min(low[u],dfn[v]);
}
if(low[u]>=dfn[u]){ //判断U是否分量的根
gc++;
int i;
do{
i=sTar.top(); ins[i]=0;
gid[i]=gc; sTar.pop(); //分量出栈
}while(i!=u); //出栈至当前结点,包括当前结点
}
}