• Book---强连通分量


    这几天一直在做强连通,现在总结一小下

    1.定义

    在一个有向图中,如果任意的两个点都是相互可达的,就说这个图是强连通的,有向图的极大强连通子图,称为强连通分量

    2.求法

    学的是白书上的tarjan算法

    用到了DFS的时间戳

    假设一个强连通分量C,其中的第一个点是 P,那么DFS下去,就一定能够找到一个K点,返回P点,这条DFS路径上的点就处于这个强连通分量C中

    假如现在发现节点v,同时发现节点v最远只能够到达节点u,那么节点u就是这个强连通分量最先被发现的节点

    这样就转化成了求一个点u最远能够到达的的祖先的d值

    所以要定义一个low[]数组为节点u最早能够追溯到的祖先的pre[v]的值,pre[v]为节点v的时间戳

    void dfs(int u){
        low[u] = pre[u] = ++dfs_clock;
        S.push(u);
        for(int i = first[u];~i;i = e[i].next){
            int v = e[i].v;
            if(!pre[v]){//子节点还没有被搜过,则搜下去,回溯回来更新low值 
                dfs(v);
                low[u] = min(low[u],low[v]);
            }
            else if(!sc[v]) low[u] = min(low[u],pre[v]);//如果当前节点不属于其他scc,且已经被访问过,说明它是当前节点的祖先节点,直接用它的low更新 
        }
        if(pre[u] == low[u]){
            scnt++;
            for(;;){
                int x = S.top();S.pop();
                sc[x] = scnt;
               // scn[scnt]++;这里可以统计一个连通分量里面有多少个点,或者当点有点权的时候,算出这个连通分量的权值 
                if(x == u) break;
            }
        }
    }
    
    void find_scc(){
        while(!S.empty()) S.pop();
        scnt = dfs_clock = 0;
        memset(low,0,sizeof(low));memset(pre,0,sizeof(pre));
        memset(sc,0,sizeof(sc));memset(scn,0,sizeof(scn));
        
        for(int i = 1;i <= n;i++) if(!pre[i]) dfs(i);
    }

    3.现在做到的一些题目

    现在做到的题目还是挺有限的,把自己做的总结下---以后遇到再补

    (1)判断是否是一个强连通图

    1)直接给一个有向图,判断是不是强连通的

    hdu 1269

    2) 附加一点限制的

    加一个限制这个强连通分量里面的节点个数大于1的,tarjan算法里面直接再统计一下个数

    poj 3180

    ( 2 )和入度出度有关的

    1)加入几条边使得整个图强连通

    白书上强连通那里的第一道例题

    先tarjan,找出所有的强连通分量

    再缩点,

    再统计图的入度,出度,

    另入度为0的有c1个,出度为0的有c2个,max(c1,c2)就是要求的

    la 4287

    hdu 2767

    hdu 3836

    这三道都是一样的

    2)从哪些点出发,使得所有的点都能够走到

    缩点,缩点后所有入度为0的就是要求的

    hdu 1827 找入度为0的连通块,还附加了一个权值

    poj 1236 max(c1,c2),和输出入度为0的连通分量的个数

    poj 2553 统计出度为0的块

    poj 2186 找有几个点是别的点都能够到达的,统计出度为0的块的个数c,

                  注意c > 1的情况,出度为0的块里面的点是相互不能够到达的,应该输出0

    poj 2375 将图转化以后就是求max(c1,c2)

    (3)和别的结合的

    一般要用到缩点,缩完点之后形成一个有向无环图,构成一个DAG,

    就可以dp,dfs,spfa

    uva 11324

    先求出所有强连通,再缩点,缩点完之后建立一个新的图

    建图的办法是,扫一遍原来所有的边,如果发现这条边的两个端点u,v处在不同的连通分量中,就在sc[u],sc[v]之间连一条边

    则转化成求DAG上权最大的路径

    还可以有另一种办法

    加一个源点进去,将这个源点与缩点完之后所有入度为0的点连一条边

    再spfa求出权最大的路径

    poj 3160和这题一样

    poj 2762 缩点之后拓扑排序

    poj 3114 缩点之后dijkstra,用floyd会t掉

    poj 3592 图转化一下以后,spfa

    现在就做了这些----

    看的这两篇博客做得题目---

    http://blog.csdn.net/accelerator_/article/details/40349411

    http://blog.csdn.net/u013013910/article/category/2509879

  • 相关阅读:
    LinqExtensions
    CsvWriter
    循环遍历清理Kubernetes中异常的pod
    Kubernetes存储——rook-ceph
    Kubernetes存储——glusterfs(集群)
    Linux环境变量配置
    Kubernetes存储——ceph(集群)
    Kubernetes存储——NFS
    Kubernetes 亲和性调度
    ceph集群运维
  • 原文地址:https://www.cnblogs.com/wuyuewoniu/p/4701112.html
Copyright © 2020-2023  润新知