來自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]);
}
}