用了半天的时间将强连通分量中的trajan算法及其代码实现这部分终于理解通透了。下面是我针对一道例题对其进行的阐释。
题目大意:
给你一个有向图,问你在图中最少要加多少条边能使得该图变成一个强连通图.题目思路:
首先我们求出该图的各个强连通分量,然后把每个强连通分量看出一个点(即缩点),然后我们得到了一个有向无环图(DAG).
对于一个DAG,我们需要添加max(a,b)条边才能使其强连通.其中a为DAG中出度为0的点总数,b为DAG中入度为0的点总数.
注意特殊情况:如果图已经强连通了,我们需要添加的边是0条,而不是1条.这道题是参照http://blog.youkuaiyun.com/u013480600/article/details/31805017经过自己的理解,将代码进行的分析。
感受:
运用了缩点,学会了找出入度为0的点的求法
#include<iostream>
#include<stdio.h>
#include<vector>
#include<stack>
#include<string.h>
#include<algorithm>
const int maxn=20000+10;
using namespace std;
vector<int>G[maxn];
stack<int>S;
int dfs_clock;
int scc_cnt;//强连通分量的个数
int n,m;
int pre[maxn];
int low[maxn];
int sccno[maxn];
bool in0[maxn],out0[maxn];
void dfs(int u)
{
pre[u]=low[u]=++dfs_clock;
S.push(u);//每搜一个就将其存入stack
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(!pre[v])//当pre为0的时候,就是还没有初始化,可见还没有搜到这个点。代替了visit
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else if(!sccno[v])//说明v还在G图里.值为0说明还未被踢
{
low[u]=min(low[u],low[v]);//这里有的人也写成low[u]=min(low[u],pre[v]),实际上结果都一样,只不过pre的值始终不变。而low的值一直在更新
}
}
if(low[u]==pre[u])//说明u点是强分量起点
{
scc_cnt++;
while(true)
{
int x=S.top();
S.pop();
sccno[x]=scc_cnt;//在这个地方进行了缩点操作,sccno数组记录的就是缩点后的值
if(x==u)
break;
}
}
}
void find_scc(int n)//此处将预处理和找scc强连通图进行了结合
{
scc_cnt=dfs_clock=0;
memset(pre,0,sizeof(pre));
memset(sccno,0,sizeof(sccno));
for(int i=0;i<n;i++)
{
if(!pre[i])
dfs(i);
}
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
G[i].clear();
}
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
u--,v--;
G[u].push_back(v);
}
find_scc(n);
for(int i=1;i<=scc_cnt;i++)
{
in0[i]=out0[i]=true;
}
for(int u=0;u<n;u++)
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(sccno[u]!=sccno[v])
{
out0[sccno[u]]=in0[sccno[v]]=false;//由于u->v,u的入度为0,出度不为0;而v反之。所以这个出入对应要消掉。in0[]为true表示入度为0,out[]为true表示出度为0
}
}
}
int a=0;int b=0;
for(int i=1;i<=scc_cnt;i++)
{
if(in0[i])
a++;
if(out0[i])
b++;
}
int ans=max(a,b);
if(scc_cnt==1)//这一步一定要有。因为此图是一个强连通,则添加的为0
ans=0;
printf("%d\n",ans);
}
return 0;
}
博客详细介绍了如何运用Trajan算法解决强连通分量问题,通过分析HDU 2767题目实例,阐述了缩点过程及找出入度为0的点的方法,帮助读者深入理解该算法。

被折叠的 条评论
为什么被折叠?



