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);
    }
    
  • 相关阅读:
    PAT 1010. 一元多项式求导 (25)
    PAT 1009. 说反话 (20) JAVA
    PAT 1009. 说反话 (20)
    PAT 1007. 素数对猜想 (20)
    POJ 2752 Seek the Name, Seek the Fame KMP
    POJ 2406 Power Strings KMP
    ZOJ3811 Untrusted Patrol
    Codeforces Round #265 (Div. 2) 题解
    Topcoder SRM632 DIV2 解题报告
    Topcoder SRM631 DIV2 解题报告
  • 原文地址:https://www.cnblogs.com/DarthVictor/p/13930694.html
Copyright © 2011-2022 走看看