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

Book---强连通分量

时间:2015-08-04 10:54:05      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:

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

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

 

Book---强连通分量

标签:

原文地址:http://www.cnblogs.com/wuyuewoniu/p/4701112.html

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