来自hiho的第五十二周,参考链接:http://hihocoder.com/contest/hiho52/problem/1
//tarjan中可见dfs_pos,low数组不需要初始化
//如果有多个联通分块,那么就要枚举每个未访问过的点进行tarjan,进行tarjan前先将fa[i] = -1
//这里的se为set,存放割点;edge为vector<pair<int,int> >,存放割边
void tarjan(int u)
{
int num_son = 0;//以当前点为树根的子树的个数
vis[u] = 1;
dfs_pos[u] = low[u] = ++jishu;//dfs_pos为dfs序,low[u]是dfs序最小的祖先(没有则为自己)
for(int i = head[u];~i;i = e[i].nex)
{
int v = e[i].v;
if(!vis[v])
{
num_son++;
fa[v] = u;//fa是父亲
tarjan(v);
low[u] = min(low[u],low[v]);//递归求dfs序最小的的祖先
if(fa[u] == -1 && num_son > 1)//若当前节点没有父亲且有两个或两个以上子树,则这个点必为割点
se.insert(u);
if(fa[u] != -1 && low[v] >= dfs_pos[u])//若当前点存在父亲,且他的儿子中没有回边连到u或者u的祖先中,此点为割点
se.insert(u);
if(low[v] > dfs_pos[u])//他的儿子没有回边连到u的祖先中
edge.push_back(pii(min(u,v),max(u,v)));
}
else if(v != fa[u])//如果拜访到已经被访问的点
low[u] = min(low[u],low[v]);
}
}