您的位置:首页 > 其它

强连通分量scc

2013-12-14 20:03 295 查看
给出一个有向图 , 要求这个图中的所有强连通分量 (一个单独的点也是强连通分量 , 这点和无向图的双连通分量不同 ,
他是一条边就是双连通分量)

这里延伸出一个题目 , 给出一个有向图 , 请问最小需要连接多少边才能让这个图变成强连通图 。

解法:先把图中的强连通分量都求出来 , 然后再把每个强连通分量缩成一个点 , 就能得到一个DAG图 , 然后最小值 = max(a ,
b) , a表示入度为0的点 , b表示进度为0的点。

要注意的一点:当整个图就是一个强连通图时 , 则需要增加的边为0;

代码:

#include

#include

#include

#include

#include

#include

using namespace std;

const int MAXN = 1000;

vectorgrap[MAXN] ;

int pre[MAXN] , lowlink[MAXN] , sccno[MAXN] , dfs_clock ,
scc_cnt;

stacks;

int n , m;

void init()

{

    for(int i =
0 ; i <= n; i++)

       
grap[i].clear();

    memset(pre ,
0 , sizeof(pre));

    memset(sccno
, 0 , sizeof(sccno));

    dfs_clock =
scc_cnt = 0;

}

void dfs(int u)

{

    pre[u] =
lowlink[u] = ++dfs_clock;

   
s.push(u);

    for(int i =
0 ; i < grap[u].size() ; i++)

    {

       
int v = grap[u][i];

       
if(!pre[v])

       
{

           
dfs(v);

           
lowlink[u] = min(lowlink[v] , lowlink[u]);

       
}

       
else if(!sccno[v])

       
{

           
lowlink[u] = min(lowlink[u] , pre[v]) ;

       
}

    }

   
if(lowlink[u] == pre[u])

    {

       
scc_cnt++;

       
for(; ;)

       
{

           
int x = s.top() ; s.pop();

           
sccno[x] = scc_cnt;

           
if(x == u)  break;

       
}

    }

}

int main()

{

   
while(scanf("%d %d" , &n , &m) != EOF)

    {

       
init();

       
int i , x , y;

       
for(i = 0 ; i < m; i++)

       
{

           
scanf("%d %d" , &x , &y);

           
grap[x].push_back(y);

       
}

    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: