• 谈谈Tarjan算法


    Tarjan算法是一系列用dfs解决图论问题的算法,由美国计算机科学家Tarjan提出。

    首先先分析有向图中Tarjan算法的应用:求有向图强连通分量。

    首先介绍一些在Tarjan算法中特殊数组的定义,这个定义怎么提出来的咱也不知道,咱也不敢问。

    一个是dfn数组,表示dfs搜索的时间戳,也就是第几个搜索到这个点。另一个是low数组,记录的是某个点经过若干条树边和至多一条非树边到达的最小的dfn。

    再说说什么是非树边,树边。树边感性理解就是dfs会得到一棵dfs搜索树,然后这棵搜索树上的边就是树边,对应的不在树上的就是非树边。而非树边又分两种,返祖边和横叉边。好吧其实非树边具体是啥没用2333。

    那么感性理解一下我们大致可以得到一个式子:low[u] = min(low[v],low[u]),u表示当前节点,v表示这个节点能到的节点。显然对于节点u,如果它的子节点v的low更小,换句话说v可以到达一个dfn更小的点,那么u同样可以经过u,v之间的树边到达那个dfn更小的点。

    那如果某个点经过一顿操作,最后low值和dfn值仍相等,说明这个点到不了之前的点了,那这个点就是一个强连通分量的根。如果我们维护一个栈,把每个搜到的点放进去,如果搜完发现一个点low和dfn相等就把这个点以及栈里在它上面的点弹出去。因为这个点上面的点都是这个点可以到的点,都属于同一个强连通分量。

    好的算法就结束了。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<stack>
      6 #include<queue>
      7 #define N 10010
      8 #define M 100010
      9 #define B printf("Break
    ");
     10 using namespace std;
     11 int head[N],nxt[M],to[M],val[N],in[N];
     12 int n,m,cnt;
     13 void add(int u,int v)
     14 {
     15     nxt[++cnt] = head[u];
     16     head[u] = cnt;
     17     to[cnt] = v;
     18     in[v]++;
     19     return;
     20 }
     21 void reset()
     22 {
     23     memset(head,0,sizeof(head));
     24     memset(nxt,0,sizeof(nxt));
     25     memset(to,0,sizeof(to));
     26     memset(in,0,sizeof(in));
     27     cnt = 0;
     28 }
     29 int dfn[N],low[N],tim;
     30 int scc[N];
     31 bool vis[N];
     32 stack<int>s;
     33 void tarjan(int u)
     34 {
     35     dfn[u] = low[u] = ++tim;
     36     vis[u] = 1;
     37     s.push(u);
     38     for(int i = head[u];i;i = nxt[i])
     39     {
     40         int v = to[i];
     41         if(!dfn[v])
     42         {
     43             tarjan(v);
     44             low[u] = min(low[u],low[v]);
     45         }
     46         else if(vis[v])
     47         {
     48             low[u] = min(low[u],dfn[v]);
     49         }
     50     }
     51     if(dfn[u] == low[u])
     52     {
     53         while(s.top() != u)
     54         {
     55             scc[s.top()] = u;
     56             vis[s.top()] = 0;
     57             val[u] += val[s.top()];
     58             s.pop();
     59         }
     60         s.pop();
     61         scc[u] = u;
     62         vis[u] = 0;
     63     }
     64 }
     65 int dis[N];
     66 int topo_sort()
     67 {
     68     queue<int>q;
     69     for(int i = 1;i <= n;i++)
     70     {
     71         if(scc[i] == i && !in[i])
     72         {
     73             q.push(i);
     74             dis[i] = val[i];
     75         }
     76     }
     77     while(q.size())
     78     {
     79         int u = q.front();
     80         q.pop();
     81         for(int i = head[u];i;i = nxt[i])
     82         {
     83             int v = to[i];
     84             dis[v] = max(dis[v],dis[u] + val[v]);
     85             in[v]--;
     86             if(!in[v]) q.push(v);
     87         }
     88     }
     89     int ans = 0;
     90     for(int i = 1;i <= n;i++) ans = max(ans,dis[i]);
     91     return ans;
     92 }
     93 int from[M],tto[M];
     94 int main()
     95 {
     96     scanf("%d %d",&n,&m);
     97     for(int i = 1;i <= n;i++)
     98     {
     99         scanf("%d",&val[i]);
    100     }
    101     for(int i = 1;i <= m;i++)
    102     {
    103         scanf("%d %d",&from[i],&tto[i]);
    104         add(from[i],tto[i]);
    105     }
    106     for(int i = 1;i <= n;i++)
    107     {
    108         if(!dfn[i]) tarjan(i);
    109     }
    110     reset();
    111     for(int i = 1;i <= m;i++)
    112     {
    113         int sf = scc[from[i]],st = scc[tto[i]];
    114         if(sf != st)
    115         {
    116             add(sf,st);
    117         }
    118     }
    119     printf("%d",topo_sort());
    120 }
    有向图缩点
  • 相关阅读:
    Oracle数据库物理结构
    Oracle 性能调优之:使用 V$SQL_PLAN 视图查询内存中的执行计划
    Oracle的操作系统身份认证(转)
    Oracle表空间知识
    Oracle数据库LOGGING&NOLOGGING模式概述
    使用插件bootstrap-table实现表格记录的查询、分页、排序等处理
    项目thymeleaf
    Comparable和Comparator的区别
    AJAX
    thymeleaf 基础
  • 原文地址:https://www.cnblogs.com/lijilai-oi/p/10809915.html
Copyright © 2020-2023  润新知