您的位置:首页 > 产品设计 > UI/UE

强连通分量(缩点+求出入为0的点的个数)HDU 2767 Proving Equivalences

2018-01-22 16:18 579 查看
用了半天的时间将强连通分量中的trajan算法及其代码实现这部分终于理解通透了。下面是我针对一道例题对其进行的阐释。

题目大意:

给你一个有向图,问你在图中最少要加多少条边能使得该图变成一个强连通图.
题目思路:

首先我们求出该图的各个强连通分量,然后把每个强连通分量看出一个点(即缩点),然后我们得到了一个有向无环图(DAG).

对于一个DAG,我们需要添加max(a,b)条边才能使其强连通.其中a为DAG中出度为0的点总数,b为DAG中入度为0的点总数.

注意特殊情况:如果图已经强连通了,我们需要添加的边是0条,而不是1条.
这道题是参照http://blog.csdn.net/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;

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