本题可在大白书的322页找到。
题意:给你一些有向边,问你至少需要加多少条边使之整个图强连通。
思路:先强连通缩点,缩点之后的图就不连通了,如果缩点后的点的入度为零,则没有出去的边,就必须加一条出去的边,才可以和其他点连通,同理,出度为零的也要加边,所以最后所需要加的最少的边为max(入度为零的点,出度为零的点)。
本题其实和hdu3836类似
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 20009;
const int maxm = 50009;
struct node
{
int v,next;
}eg[maxm];
int head[maxn],in[maxn],out[maxn],belong[maxn];
int insta[maxn],dfn[maxn] ,low[maxn],sta[maxn];
int tot,Index,top,color,n;
inline int min(int a,int b){return a < b ? a : b;}
inline int max(int a,int b){return a > b ? a : b;}
inline void add(int a,int b)
{
eg[tot].v = b;
eg[tot].next = head[a];
head[a] = tot++;
}
void init()
{
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(sta,0,sizeof(sta));
memset(head,-1,sizeof(head));
memset(belong,0,sizeof(belong));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
tot = Index = top = color = 0;
}
void tarjan(int u)
{
dfn[u] = low[u] = ++Index;
sta[top++] = u;
insta[u] = 1;
for(int i = head[u];i+1;i=eg[i].next)
{
int v= eg[i].v;
if(!dfn[v])
{
tarjan(v);
low[u] = min(low[u],low[v]);
}else if(insta[v])
{
low[u] = min(low[u],dfn[v]);
}
}
if(low[u] == dfn[u])
{
int v;
color ++; //强连通个数
do
{
v = sta[--top];
insta[v] = 0;
belong[v] = color;
}while(u != v);
}
}
void buildtree()
{
for(int u=1;u<=n;u++)
{
for(int i = head[u];i+1;i=eg[i].next)
{
int v = eg[i].v;
if(belong[u] != belong[v]) //缩点
{
out[belong[u]] ++;
in[belong[v]] ++;
}
}
}
}
void work()
{
int i,a=0,b=0;
for(i = 1;i<=n;i++)
if(!dfn[i]) tarjan(i);
buildtree();
for(i=1;i<=color;i++)
{
if(in[i] == 0) a++; //入度为零的点
if(out[i] == 0) b++; //出度为零的点
}
if(color == 1) //图本身是强连通的就不需要
printf("0\n");
else
printf("%d\n",max(a,b));
}
int main()
{
int a,b,m,i;
int t;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
}
work();
}
return 0;
}
/*
2
3 2
1 2
1 3
3 2
1 2
1 3
*/
UVa LA 4287 强连通 (类似 hdu 3836),布布扣,bubuko.com
原文:http://www.cnblogs.com/BruceNoOne/p/3854201.html