tarjan_割点无向图

int dfn[MAXN],cTime,low[MAXN]; //时间戳,时间戳计数,祖先时间。  
int block[MAXN],bc; // 块数组,块计数。  
int cut[MAXN];//记录每点属于几个割点块,注意根结点初始化为 0,其余
int ins[MAXN]; stack<int> sTar;  //入栈标志,辅助栈  
void Tarjan(int u, int fa ){ 
  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(v == fa)continue; //如果是【u v】边跳过  
    if(!dfn[v]){ 
      Tarjan(v,u); 
      low[u]=min(low[u],low[v]);//利用子孙,更新能回指的祖先
      if(low[v]>=dfn[u]){    //如果u是割点  
        bc++;cut[u]++;    //u属于的割点块+1  
        int i;block[u]=bc;  //u点必定属于当前块,为了根结
        do{ 
          i=sTar.top(); ins[i]=0;   //结点标记块号,块出
          block[i]=bc; sTar.pop(); 
        }while(i!=v); 
      } 
    } 
    else     //记录U能回指的最早祖先的时间戳 if(ins[v]) 
      low[u]=min(low[u],dfn[v]); 
  } }

int dfn[MAXN],cTime,low[MAXN]; //时间戳,时间戳计数,祖先时间。 
int block[MAXN],bc;  // 块数组,块计数。  
int ins[MAXN]; stack<int> sTar; //入栈标志,辅助栈  
void TarjanEdge(int u, int fa ){ 
  dfn[u]=low[u]=++cTime;    //时间戳与祖先时间初始化  
  ins[u]=1; sTar.push(u); //入栈  
  bool flag=1; 
  for(int i=p[u];i;i=edge[i].next){  //递归处理所有子结点  
    int v=edge[i].v; 
    if(v == fa && flag){flag=0; continue;} //跳过一条【u v】边
    if(!dfn[v]){ 
      TarjanEdge(v,u); 
      low[u]=min(low[u],low[v]);  //利用子孙,更新能回指的祖
      if(low[v]>dfn[u]){    //如果是割边  
        bc++; 
        int i; 
        do{ 
          i=sTar.top(); ins[i]=0;   //结点标记块号,块
          block[i]=bc; sTar.pop(); 
        }while(i!=v); 
      } 
    } 
    else     //记录U能回指的最早祖先的时间戳 if(ins[v]) 
      low[u]=min(low[u],dfn[v]); 
  } 

猜你喜欢

转载自blog.csdn.net/to_more_excellent/article/details/81263350