tarjan求割点and割边

tarjan 求割点

//tarjan find cut point
int stack[10000];
int dfn[10000];
int low[10000];
int stop;
int dfn_cnt;
bool iscut[1000];
int root;
/*
割点判断定理:
对于一个点 u,有以下两种情况:
如果 u 是根节点,那么当它有多于一个子树时,它就是割点
如果 u 不是根节点,并且 u 为 v 在搜索树中的父亲,当 dfn[ u ] ≤ low[ v ] 时,它就是割点
【割点】 
*/
void tarjan(int x){
	low[x] = dfn[x] = ++dfn_cnt;
	stack[++top] = x;
	int child = 0;
	for(int i = head[x];i!=0;i = edges[i].next){
		if(!dfn[i]){//下一个点没有被访问过; 
			tarjan(edges[i].t);
			child++;
			low[x] = min(low[x],low[edges[i].t]);
			if(x==root&&child>1){//点x是树根节点并且有超过两个子树,那么它是割点 
				iscut[x] = true;
			}
			if(x!=root&&low[edges[i].t]>=dfn[x]){//如果x不是树根节点且dfn[u]<=low[v]那么它是割点,见割点判断定理 
				iscut[x] = true;
			}
		}else{
			low[x] = min(low[x],dfn[edges[i].t]) ;
		}
	}
}
//root 为每个搜索树的开始点 
//eg:
	for(int i = 1;i<=n;i++){
		if(!dfn[i]){//这个点没被访问过
			root = i;
			tarjan 
			
		}
	}

割边

/*
判定定理:如果一条搜索树上的边,连接着两个结点xy,且x是y的父亲,且满足low[y]>dfn[x],那么就是割边了
*/
//这个板子可能暂时有问题
void tarjan(int x,int fa){
	low[x] = dfn[x] = ++dfn_cnt;
	for(int i = head[x];i!=0;i = edges[i].next){
	    int v = edges[i].t;
	    if(!dfn[v]){
	        tarjan(v,x);
	        low[x]=min(low[v],low[x]);
	       if(low[v]>dfn[x]){
	        iscut[i]=iscut[i^1]=true;//判定定理
	       }
	    }else if(dfn[x]>dfn[v]&&v!=fa){
	       low[x] = min(dfn[v],low[x]);
	    }
	}
}