码迷,mamicode.com
首页 > 其他好文 > 详细

tarjan

时间:2019-08-04 15:32:30      阅读:95      评论:0      收藏:0      [点我收藏+]

标签:操作   变量   lse   next   pre   关系   tarjan   names   min   

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\n",++test);
        for(int i=1;i<=n;i++)
           if(block[i]>1){
                       printf("  SPF node %d leaves %d subnets\n",i,block[i]);
                       flag=1;
              }
           if(!flag)printf("  No SPF nodes\n");
        printf("\n");   
    }
    return 0;
}

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

tarjan

标签:操作   变量   lse   next   pre   关系   tarjan   names   min   

原文地址:https://www.cnblogs.com/tushukai/p/11298116.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!