强连通分量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);
}
他是一条边就是双连通分量)
这里延伸出一个题目 , 给出一个有向图 , 请问最小需要连接多少边才能让这个图变成强连通图 。
解法:先把图中的强连通分量都求出来 , 然后再把每个强连通分量缩成一个点 , 就能得到一个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);
}
相关文章推荐
- uva 10765(无向双连通量)
- FZU 2103 组合概率
- 我的博客今天0岁51天了,我领取了…
- poj 1325
- uva 11865 stream my contest
- uva 11865 stream my contest
- 二分图的最佳完美匹配(和一些变形…
- 有向图最小生成树——最小树形图(朱…
- 每个点与点之间的瓶颈路
- LA 5713 Qin&nbsp…
- uva 11354 Bond
- 最小生成树的一些性质和理解
- poj 2485 简单的最小生…
- 我的博客今天0岁42天了,我领取了…
- LA 4080 Warfare A…
- hdu 2433 最短路树
- 【快速】排序, T(n) = O(nlgn),O(n^2) S(n) = O(lgn) --- 不稳定
- (C# 基础) 类访问修饰符
- LA 3713 Astronauts
- LA 3211 Now or later