主要是给自己的,一些易忘知识点的总结吧。
割点:根的有俩儿子就是割点,其他的点如果子树中有儿子连接不到它祖先那里去就是割点(即存在low[son[u]]>=dfn[u])。
桥:结点u的子结点v的后代通过反向边只能连回v(low[v]>dfn[u])。
void tarjan(int u){ dfn[u]=low[u]=++order; bool flag=false; for (int i=0;i<edge[u].size();i++){ int v=edge[u][i]; if(!dfn[v]){ son[u]++; father[v]=u; tarjan(v); if(low[v]>=dfn[u]) flag=true; //点u为割点 if(low[v]>dfn[u]) cutedge.push_back(make_pair(min(v,u),max(v,u))); //边v-u为割边 low[u]=min(low[u],low[v]); } else if(v!=father[u]) low[u]=min(low[u],dfn[v]); } //根节点若有两棵或两棵以上的子树则该为割点 //非根节点若所有子树节点均没有指向u的祖先节点的回边则为割点 if((father[u]==0&&son[u]>1)||(father[u]&&flag)) cutpoint.push_back(u); }