• tarjan


    TARJAN算法

    我先介绍一下这个算法是来干啥的:
    它的用处是求强连通分量。 那么,强连通分量又是啥??

    在一个有向图中,
    强连通:如果两个顶点可以相互通达,则称两个顶点 强连通(strongly connected)
    如果有向图G的每两个顶点都 强连通,称G是一个强连通图。非 强连通图有向图的极大强连通 子图,称为强连通分量(strongly connected components)。

    算法思路:

    第一点,对象图不一定是一个连通图。所以,为了判断每个点是否连通,我们引入一个时间戳。如果他==0则深搜搜他!!

    我们还要定义一个变量:low[ ]:该子树中,且仍在栈中的最小时间戳,像是确立了一个关系,low[ ]相等的点在同一强连通分量中。

    然后对于搜到的点寻找与其有边相连的点,判断这些点是否已经被搜索过,若没有,则进行搜索。若该点已经入栈,说明形成了环,.则更新low

    在不断深搜的过程中如果没有路可走了(出边遍历完了),那么就进行回溯,回溯时不断比较low[ ],去最小的low值。如果dfn[x]==low[x]则x可以看作是某一强连通分量子树的根,也说明找到了一个强连通分量,然后对栈进行弹出操作,直到x被弹出。

    算法模板:

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=1005;
    int x,y,n,id,t,flag,test;
    int dfn[N],head[N],block[N],low[N];
    struct Node{
    	int v,next;
    }e[N*N];
    int max(int A,int B) {return A>B? A:B;} 
    int min(int A,int B) {return A>B? B:A;}
    void add(int u,int v) {e[id].v=v;e[id].next=head[u];head[u]=id++;}
    #define to e[i].v
    void tj(int u)
    {
    	dfn[u]=low[u]=++t;
    	for (int i=head[u];i;i=e[i].next)
    	if (!dfn[to]) 
    	{
    		tj(to);
    		low[u]=min(low[u],low[to]);
    		if (low[to]>=dfn[u]) ++block[u];
    	}
    	else low[u]=min(low[u],dfn[to]);
    }
     
    int main(){
    	while(1){
    		scanf("%d",&x);
    		if (x==0) break;
    		memset(e,0,sizeof(e));
    		memset(dfn,0,sizeof(dfn));
    		memset(low,0,sizeof(low));
    		memset(head,0,sizeof(head));
    		id=1;t=flag=n=0;
    		scanf("%d",&y);add(x,y);add(y,x);n=max(n,x);n=max(n,y);
    		whille(1){
    			int u,v;
    			scanf("%d",&u);
    			if (u==0) break;
    			scanf("%d",&v);
    			add(u,v);add(v,u);
    			n=max(n,u);n=max(n,v);
    		}
    		for (int i=1;i<=n;i++) block[i]=1;block[1]=0;
    		tj(1);
    		printf("Network #%d
    ",++test);
    		for(int i=1;i<=n;i++)
    		   if(block[i]>1){
    			           printf("  SPF node %d leaves %d subnets
    ",i,block[i]);
    			           flag=1;
    		      }
    	       if(!flag)printf("  No SPF nodes
    ");
            printf("
    ");	
    	}
    	return 0;
    }
    

    感谢https://blog.csdn.net/yklcy_1334/article/details/54563832!!!

  • 相关阅读:
    spring 环绕通知 ProceedingJoinPoint 执行proceed方法的作用是什么
    SpringMVC之RequestContextHolder分析
    MySQL中索引不会被用到的情况
    使用Stream快速对List进行一些操作
    Vue中this.$refs[name].resetFields();的使用
    好看的字体
    转,javascript中call()、apply()、bind()的用法终于理解
    vue中的$props
    手机端页面自适应解决方案-rem布局
    查看项目里特定npm包的版本号
  • 原文地址:https://www.cnblogs.com/tushukai/p/11298116.html
Copyright © 2020-2023  润新知