• tarjan算法


    定义

    dfn[x]:DFN过程中到x点的时间
    low[x]:最小的x能达到的点的dfn
    当x进栈时dfn[x]=low[x]
    part[x]:x所在的强连通分量
    

    代码解释

    //强连通分量
    int tarjan(int x)
    {
    	d[++tot]=x;//进栈
    	dfn[x]=low[x]=++dd;//初始化dfn[]以及low[]
    	for(int i=last[x];i;i=next[i])
    	{
    		int j=to[i];
    		if(!dfn[j])//当没走过j是,遍历j
    		{
    			tarjan(j);
    			low[x]=min(low[x],low[j]);//因为x可以走到j,所以更新low[]
    		}
    		else
    		if(!part[j])//只有当j还在栈中是才可以更新low。因为当j不在栈中时,j并不能遍历到x
    			low[x]=min(low[x],low[j]);
    	}
    	if(dfn[x]==low[x])//表示x无法回溯到更小的dfn
    	{
    		num++;//num表示强连通分量个数
    		while(dfn[d[tot]]>=dfn[x])//退栈,在栈中比x后进栈的节点都与x属于同一个强连通分量
    		{
    			part[d[tot--]]=num;
    		}
    	}
    }
    
    //人工栈代码
    long long tarjan(long long x1)
    {
        z[top=1]=x1;
        while(top)
        {
            long long x=z[top];
            if(!dfn[x])
            {
                dfn[x]=low[x]=++tot;
                d[++dd]=x;
            }
            long long i;
            for(i=last[x];i;i=next[i])
            {
                if(!dfn[to[i]])
                {
                    break;
                }
                else
                if(!belong[to[i]])
                    low[x]=min(low[to[i]],low[x]);
            }
            if(!i && top>1) 
                low[z[top-1]]=min(low[z[top-1]],low[x]);
            if(!i)
            {
                if(dfn[x]==low[x])
                {
                    be++;
                    while(dd && low[d[dd]]>=dfn[x])
                    {
                        belong[d[dd]]=be;
                        sum[be]+=a[d[dd]];
                        dd--;
                    }
                }
                top--;
            }
            else
                z[++top]=to[i];
        }
    }
    
    //双连通分量
    int tarjan(int x,int fa)
    {
    	low[x]=dfn[x]=++tot;
    	d[++dd]=x;
    	for(int i=last[x];i;i=next[i])
    	{
    		int j=to[i];
    		if(i!=fa)//类似于强连通分量,只有保证不走来的边就可以了
    		{
    			if(!dfn[j])
    			{
    				tarjan(j,i^1);
    				low[x]=min(low[x],low[j]);
    			}
    			else
    				low[x]=min(low[x],low[j]);
    		}
    	}
    	if(low[x]==dfn[x])
    	{
    		num++;
    		while(low[d[dd]]>=dfn[x] && dd)
    		{
    			part[d[dd--]]=num;
    			sum[num]++;
    		}
    	}
    }
    
  • 相关阅读:
    java 基础 01 变量和注释、数据类型
    js虚拟数字小键盘
    好看的table样式
    Java8的lambda表达式和Stream API
    设计模式-模板
    【转】Git使用教程之基础篇
    Linux安装redis和部署
    【原】DjianGo Windows7下的安装
    【转】七牛云加速域名配置
    【原】Solr入门之概念和安装
  • 原文地址:https://www.cnblogs.com/chen1352/p/9043471.html
Copyright © 2020-2023  润新知