zoukankan      html  css  js  c++  java
  • 无向图的tarjan算法

    -无向图求点双联通分量 并求单环
    暂时还不知道有什么用因为不能缩点 但是好像有用
    将桥和割点分开讨论
    注意判断根是否为割点

    stack<int> W;
    ll f[maxnn];
    int scc=0;
    ll sum[maxnn];
    int ttt[maxnn];
    int ma[maxnn],mi[maxnn];
    void tarjan(int v,int fa) {
        int r;
        mark[v]=1;
        dfn[v]=low[v]=++vis;
        W.push(v);
        for(int i=las[v]; i; i=nex[i]) {
            int u=en[i];
            int d;
            if(u!=fa) {
                if(!dfn[u]) {
                    tarjan(u,v);
                    low[v]=min(low[v],low[u]);
                    if(dfn[v]==low[u]) {
                        scc++;
                        mi[scc]=v;
                        rrr[scc]=1;
                        ma[scc]=v;
                        do {
    						d=W.top();
    						rrr[scc]++;
                            mi[scc]=min(mi[scc],d);
                            ma[scc]=max(ma[scc],d);
                            W.pop();
                        } while(d!=u);
                    }
                    if(dfn[v]<low[u]) {
                        do {
                        	
    						d=W.top();
                            W.pop();
                        } while(d!=u);
                    }
                } else {
                    low[v]=min(low[v],dfn[u]);
                }
            }
        }
    }
    
    int Tarjan(int u, int fa)
    {
    int low[u] = dfn[u] = ++Time;
    for(int i = Last[u]; i; i = Next[i])
    {
    Son[u]++;
    int v = End[i];
    if(!dfn[v])
    {
    s.push(i); //i号边入栈, i是一条父子边(树枝边)
    Tarjan(v, u);
    low[u] = min(low[u], low[v]);
    if(low[v] >= dfn[u]) //对于v而言,u是割点,找到一个点双连通分量
    {
    CutPoint[u] = true; //将u标记为是割点
    BCC++; //统计双连通分量的个数
    while(true)
    {
    int k = s.top(); s.pop(); //弹出栈顶边, 编号为k
    int x=Start[k]; int y=End[k]; //x,y分别为k号边的两个端点
    if(Belong[x]!=BCC) //Belong[x]记录目前x属于那个双连通块
    { Block[BCC].push_back(x); Belong[x]=BCC; } //Block[BCC]存储属于BCC号联通块的节点的编号
    if(Belong[y]!=BCC)
    { Block[BCC].push_back(y); Belong[y]=BCC; }
    if(x==u && y==v )break; //对于v,u是割点,那么v肯定不属于当前连通块
    }
    }
    }e
    lse if(dfn[v] < dfn[u] && v != fa) //i是一条返祖边
    {
    s.push(i);
    low[u] = min(low[u], dfn[v]);
    }
    }i
    f(fa == 0 && Son[u] <= 1) CutPoint[u] = false; //前面可能误把根当作了割点。 若i为根, 且儿子个数<=1,i不是割点。
    }
    

    -无向图求边双联通分量 强行变成有向图

    
    stack<int > S;
    int sec;
    inline void tarjan(int v,int e) {
    	dfn[v]=low[v]=++vii;
    	S.push(v);
    	for(int i=las[v]; i; i=nex[i]) {
    		if((e!=-1)&&((i^1)==(e))) {
    			continue;
    		}
    		ll u=en[i];
    		if(!dfn[u]) {
    			tarjan(u,i);
    			low[v]=min(low[u],low[v]);
    		} else {
    			low[v]=min(low[v],dfn[u]);
    		}
    	}
    	ll r;
    	if(low[v]==dfn[v]) {
    		sec++;
    		do {
    			r=S.top();
    			S.pop();
    			belong[r]=sec;
    			ttt[sec]++;
    		} while(r!=v);
    	}
    }
    
    
  • 相关阅读:
    107.JsonResponse
    106.HttpResponse对象详解
    前端学习笔记系列一:2 Vue的单文件组件
    前端学习笔记系列一:1.export default / export const
    @vue-cli的安装及vue项目创建
    Github版本控制系统
    C# 篇基础知识11——泛型和集合
    C# 篇基础知识10——多线程
    C# 篇基础知识9——特性、程序集和反射
    C# 篇基础知识8——正则表达式
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11789289.html
Copyright © 2011-2022 走看看