求出强分量后缩点处理得到分支图,对分支图的每个强连通分量统计出度和入度。需要的边数就是:统计 入度=0 的顶点数 和 出度=0 的顶点数,选择两者中较大的一个,才能确保一个强连通图。
程序:
#include"string.h" #include"stdio.h" #include"iostream" #include"stack" #define inf 999999999 #define M 20009 using namespace std; stack<int>q; struct st { int u,v,next; }edge[M*3]; int belong[M],head[M],low[M],dfn[M],use[M],out[M],in[M],index,num,t,n; void init() { t=0; memset(head,-1,sizeof(head)); } void add(int u,int v) { edge[t].u=u; edge[t].v=v; edge[t].next=head[u]; head[u]=t++; } void tarjan(int u) { dfn[u]=low[u]=++index; q.push(u); use[u]=1; int i; for(i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(use[v]) { low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]) { int p; num++; do { p=q.top(); belong[p]=num; use[p]=0; q.pop(); }while(u!=p); } } void solve() { index=num=0; memset(dfn,0,sizeof(dfn)); memset(use,0,sizeof(use)); for(int i=1;i<=n;i++) { if(!dfn[i]) { tarjan(i); } } } int main() { int m,i; while(scanf("%d%d",&n,&m)!=-1) { init(); while(m--) { int a,b; scanf("%d%d",&a,&b); add(a,b); } solve(); if(num==1)//注意 { printf("0\n"); continue; } memset(out,0,sizeof(out)); memset(in,0,sizeof(in)); for(i=0;i<t;i++) { int u=edge[i].u; int v=edge[i].v; if(belong[u]!=belong[v]) { out[belong[u]]++; in[belong[v]]++; } } int max1,max2; max1=max2=0; for(i=1;i<=num;i++) { if(out[i]==0) max1++; if(in[i]==0) max2++; } printf("%d\n",max1>max2?max1:max2); } }