zoukankan      html  css  js  c++  java
  • tarjan学习笔记

    1>求强连通分量:

    这个的思路大致就是每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。

    定义DFN(u)为节点u搜索的次序编号(时间戳),Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号(即点u不经过其父节点能到达的最小dfn)。

    可求图中强连通分量个数及内容。

    代码如下(伪):

     1 void tarjan(int x)
     2 {
     3     dfn[x]=low[x]=++cnt;
     4     instack[x]=1;
     5     s.push(x);
     6     int y;
     7     for(int i=head[x];i;i=e[i].nxt)
     8     {
     9         y=e[i].to;
    10         if(!dfn[y])
    11         {
    12             tarjan(y);
    13             low[x]=min(low[x],low[y]);
    14         }
    15         else if(instack[y]) low[x]=min(low[x],dfn[y]);
    16     }
    17     y=0;
    18     if(dfn[x]==low[x])
    19     {
    20         tot++;
    21         while(x!=y)
    22         {
    23             y=s.top();
    24             s.pop();
    25             instack[y]=0;
    26             belong[y]=tot;
    27         }
    28     }
    29 }
    30 void solve()
    31 {
    32     tot=cnt=0;
    33     memset(dfn,0,sizeof(dfn));
    34     For(i,1,n)
    35         if(!dfn[i]) tarjan(i);
    36 } 
    View Code

    2>求割点、割边

    这个的算法与上面相似,只是增加了对于割点、割边的判定。

    具体判定方式为:

    割点:判断顶点U是否为割点,用U顶点的dnf值和它的所有的孩子顶点的low值进行比较,如果存在至少一个孩子顶点V满足low[v] >= dnf[u],就说明顶点V访问顶点U的祖先顶点,必须通过顶点U,而不存在顶点V到顶点U祖先顶点的其它路径,所以顶点U就是一个割点。对于没有孩子顶点的顶点,显然不会是割点。

    桥(割边):low[v] > dnf[u] 就说明V-U是桥。

    代码如下(伪):

    割点

     1 void dfs(int x,int root)
     2 {
     3     int tot=0;
     4     low[x]=dfn[x]=++id;
     5     for(int i=head[x];i;i=a[i].next)
     6     {
     7         int y=a[i].y;
     8         if(!dfn[y])
     9         {
    10             dfs(y,root);
    11             low[x]=min(low[x],low[y]);
    12             if(low[y]>=dfn[x]&&x!=root) bz[x]=1;
    13             if(x==root) tot++;
    14         }
    15         low[x]=min(low[x],dfn[y]);
    16     }
    17     if(x==root&&tot>=2) bz[root]=1;
    18 }
    19 void solve()
    20 {
    21     for(int i=1;i<=n;i++)
    22         if(!dfn[i]) dfs(i,i);
    23     for(int i=1;i<=n;i++)
    24         if(bz[i]) ans++;
    25 }
    View Code

    割边

     (类似于割点,不贴代码了先咕着)


    3>求点双、边双

    边双:如果一个无向连通图中,没有割边,那么这个无向连通图就是一个边双连通图。

    求法:tarjan求出所有割边,然后把割边去掉,就是一个个边双连通分量了。然后只要去掉割边进行dfs染色就行了。

    点双:在一个无向连通图中,如果没有割点,那么它是点双连通图。如果只有两个点,那么也是点双。一个无向图中的极大点双连通子图就是点双连通分量。

    求法:先咕着。。。


    4>点双缩点、边双缩点

     自己实现去,都求出点双边双了,就重新建个图的事。。。

  • 相关阅读:
    空值判断(is not null)
    http协议相关面试题
    Linux基本面试题。(感觉也就这几个了)
    1、了解django运行流程
    python笔试常见题
    selenium中一些可能用到的js操作
    元素判断
    二次封装
    关于在阿里云上面安装mysql遇到的一些问题。
    linux常用的一些基本命令
  • 原文地址:https://www.cnblogs.com/3soon/p/11805210.html
Copyright © 2011-2022 走看看