zoukankan      html  css  js  c++  java
  • Tarjan全家桶

    强联通分量及缩点

    #include<bits/stdc++.h>
    #define re register
    #define v e[i].to
    using namespace std;
    const int lzw=1e4+3;
    int n,m,head[lzw],tot,h[lzw],cnt,dfn[lzw],low[lzw],belong[lzw],stk[lzw],top,dfn_clock,scc_cnt,in[lzw];
    struct edge{
    	int to,next;
    }e[lzw*10],ee[lzw*10];
    void add(int a,int b){
    	e[++tot].to=b;
    	e[tot].next=head[a];
    	head[a]=tot;
    }
    void insert(int a,int b){
    	ee[++cnt].to=b;
    	ee[cnt].next=h[a];
    	h[a]=cnt;
    }
    void tarjan(int u){//强联通分量
    	dfn[u]=low[u]=++dfn_clock,stk[++top]=u;
    	for(re int i=head[u];i;i=e[i].next){
    		if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
    		else if(!belong[v]) low[u]=min(low[u],dfn[v]);
    	}
    	if(low[u]==dfn[u]){
    		scc_cnt++;
    		while(1){
    			int tmp=stk[top--];
    			belong[tmp]=scc_cnt;
    			if(tmp==u) break;
    		}
    	}
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for(re int i=1;i<=m;i++){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		add(x,y);
    	}
    	for(re int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    	for(re int j=1;j<=n;j++){//缩点
    		for(re int i=head[j];i;i=e[i].next){
    			if(belong[v]==belong[j]) continue;
    			insert(belong[j],belong[v]),in[belong[v]]++;
    		}
    	}
    	return 0;
    }
    

    割点

    (large {color{red} {注意判根!}})

    void tarjan(int u,int fa){
          dfn[u]=low[u]=++dfn_clock;
    	int ch=0;
    	for(re int i=head[u];i;i=e[i].next){
    		if(!dfn[v]){
    			tarjan(v,u),low[u]=min(low[v],low[u]);
    			if((!fa&&++ch>1)||(fa&&low[v]>=dfn[u])) cut[u]=1;
    		}
    		else if(v!=fa) low[u]=min(low[u],dfn[v]);
    	}
    }
    

    点双联通分量

    void tarjan(int u,int fa){
    	dfn[u]=low[u]=++dfn_clock;
    	stk[++top]=u;
    	for(re int i=head[u];i;i=e[i].next){
    		if(v==fa) continue;
    		if(!dfn[v]){
    			tarjan(v,u);
    			low[u]=min(low[u],low[v]);
    			if(low[v]>=dfn[u]){
    				bcc_cnt++;
    				while(1){
    					int tmp=stk[top--];
    					all[bcc_cnt].push_back(tmp);
    					if(tmp==v) break;
    				}
    				all[bcc_cnt].push_back(u);
    			}
    		}else low[u]=min(low[u],dfn[v]);
    	}
    }
    

    void tarjan(int u,int fa){
    	dfn[u]=low[u]=++dfn_clock;
    	for(re int i=head[u];i;i=e[i].next){
    		if(v==fa) continue;
    		if(!dfn[v]){
    			tarjan(v,u);
    			low[u]=min(low[u],low[v]);
    			if(low[v]>dfn[u]) e[i].flag=e[i^1].flag=1;
    		}else low[u]=min(low[u],dfn[v]);
    	}
    }
    

    边双联通分量

    桥的部分再加上(DFS)

    void dfs(int u){
    	belong[u]=cnt,vis[u]=1;
    	for(re int i=head[u];i;i=e[i].next) if((!e[i].flag)&&(!vis[v])) dfs(v);
    }
    
  • 相关阅读:
    内存映射文件原理探索(转)
    inux内存映射和共享内存理解和区别
    MySQL中的sleep函数介绍
    flask源码解析之上下文为什么用栈
    linux system函数详解
    Python中的可迭代对象、迭代器和生成器,协程的异同点
    GB2312汉字区位码、交换码和机内码转换方法 (ZT)
    pthread_cond_signal该放在什么地方?
    IPC介绍——10个ipcs例子
    lsof
  • 原文地址:https://www.cnblogs.com/DarthVictor/p/13930694.html
Copyright © 2011-2022 走看看