• tarjan缩点相关知识及代码


    emmm原谅我确实是找不到不用缩点的tarjan题才会想到自学一下缩点这个东西的。。

    题目没有,只能自己出数据并手动模拟。。。

    首先看一张图(懒得画,还是看输入数据吧,劳烦自行画图。。)

    7 9(n个点,m个关系,以下m行每一行为两个点a,b之间有a指向b的一条有向边)
    1 2
    2 3
    3 1
    3 4
    4 5
    4 7
    7 5
    6 7
    6 5

    在画过图之后,显然可知,1 2 3这3个节点在一个强连通分量中(如果不理解强连通分量自行度娘哦),将其缩点,并利用1 2 3结点的边关系将缩成的点与其他点融合,形成新的图。好的,那么只需要套一遍tarjan,将每个强连通分量内的点赋值为该强连通分量的编号,再利用新的链式前向星存储新的图,已达到缩点的功效

     1 #include<set>
     2 #include<map>
     3 #include<list>
     4 #include<queue>
     5 #include<stack>
     6 #include<string>
     7 #include<cmath>
     8 #include<ctime>
     9 #include<vector>
    10 #include<bitset>
    11 #include<memory>
    12 #include<utility>
    13 #include<cstdio>
    14 #include<sstream>
    15 #include<iostream>
    16 #include<cstdlib>
    17 #include<cstring>
    18 #include<algorithm>
    19 using namespace std;
    20 const int N=100005;
    21 
    22 stack <int> q;
    23 int tot,n,m,num;
    24 int head[N],next[N],to[N],head2[N],next2[N],to2[N],dfn[N],low[N],f[N];//后缀为2的记录的是缩点后所得图的信息
    25 bool visit[N];
    26 
    27 inline int mi(int a,int b){return a<b?a:b;}
    28 inline int ma(int a,int b){return a>b?a:b;}
    29 
    30 inline void add(int u,int v){//对读入的数据进行处理
    31     next[++tot]=head[u];
    32     head[u]=tot;
    33     to[tot]=v;
    34 }
    35 
    36 inline void add2(int u,int v){//对缩点后的数据进行处理
    37     next2[++tot]=head2[u];
    38     head2[u]=tot;
    39     to2[tot]=v;
    40 }
    41 
    42 void tarjan(int u){//tarjan板子
    43     dfn[u]=low[u]=++tot;
    44     visit[u]=1;
    45     q.push(u);
    46     for(int i=head[u];i;i=next[i]){
    47         if(!dfn[to[i]]){
    48             tarjan(to[i]);
    49             low[u]=mi(low[u],low[to[i]]);
    50         }
    51         else if(visit[to[i]]){
    52             low[u]=mi(low[u],low[to[i]]);
    53         }
    54     }
    55     if(dfn[u]==low[u]){
    56         int v;
    57         num++;
    58         do{
    59             v=q.top();
    60             q.pop();
    61             visit[v]=0;
    62             f[v]=num;//记录v节点存在的强连通分量编号
    63         }while(v!=u&&!q.empty());
    64     }
    65 }
    66 
    67 int main(){
    68     scanf("%d%d",&n,&m);
    69     for(int i=1;i<=m;i++){
    70         int u,v;
    71         scanf("%d%d",&u,&v);
    72         add(u,v);
    73     }
    74     tot=0;
    75     for(int i=1;i<=n;i++){
    76         if(!dfn[i]){
    77             tarjan(i);
    78         }
    79     }
    80     tot=0;
    81     for(int i=1;i<=n;i++){
    82         for(int j=head[i];j;j=next[j]){
    83             if(f[i]!=f[to[j]]){//去除在同一强连通分量的节点情况
    84                 add2(f[i],f[to[j]]);
    85             }
    86         }
    87     }
    88     return 0;
    89 }

    那着就是缩点了,我个人感觉并不是很困难

  • 相关阅读:
    Python的单元测试(二)
    Python的单元测试(一)
    未知道——广场式的真匿名交流网站(一)
    xpath提取多个标签下的text
    清空Github上某个文件的历史版本
    如何正确使用日志Log
    使用AWS亚马逊云搭建Gmail转发服务(三)
    玩转Windows服务系列——Windows服务小技巧
    玩转Windows服务系列——服务运行、停止流程浅析
    玩转Windows服务系列——无COM接口Windows服务启动失败原因及解决方案
  • 原文地址:https://www.cnblogs.com/hahaha2124652975/p/11144161.html
Copyright © 2020-2023  润新知