这也是道强连通分量的题;
题目要求我们求出最少需要添加多少条边让整个图变成一个强连通分量;
思路很简单,直接缩点,然后找出所有点中有多少出度为0,入度为0的点,最大的那个就是题目所求;
贴代码:
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 #include<algorithm> 5 #include<stack> 6 #define maxn 50005 7 using namespace std; 8 vector<int>ve[maxn]; 9 int dfn[maxn],low[maxn],ans,n,m,nncount,b[maxn]; 10 int from[maxn],to[maxn],cntin[maxn],cntout[maxn]; 11 bool instack[maxn]; 12 stack<int>q; 13 14 void tarjin(int x) 15 { 16 dfn[x]=low[x]=++nncount; 17 instack[x]=1; 18 q.push(x); 19 int l=ve[x].size(); 20 for(int i=0; i<l; i++) 21 { 22 int v=ve[x][i]; 23 if(!dfn[v]) 24 { 25 tarjin(v); 26 low[x]=min(low[x],low[v]); 27 } 28 else if(instack[v]) 29 low[x]=min(low[x],dfn[v]); 30 } 31 if(low[x]==dfn[x]) 32 { 33 ans++; 34 int v; 35 do 36 { 37 v=q.top(); 38 q.pop(); 39 b[v]=ans; 40 instack[v]=0; 41 }while(v!=x); 42 } 43 } 44 45 int main() 46 { 47 int x,y,t,mm1,mm2; 48 scanf("%d",&t); 49 while(t--) 50 { 51 memset(cntin,0,sizeof cntin); 52 memset(cntout,0,sizeof cntout); 53 memset(b,0,sizeof b); 54 memset(dfn,0,sizeof dfn); 55 memset(low,0,sizeof low); 56 scanf("%d%d",&n,&m); 57 for(int i=1; i<=n; i++) 58 { 59 ve[i].clear(); 60 instack[i]=0; 61 } 62 while(!q.empty()) q.pop(); 63 for(int i=1; i<=m; i++) 64 { 65 scanf("%d%d",&x,&y); 66 ve[x].push_back(y); 67 from[i]=x,to[i]=y; 68 } 69 nncount=ans=mm1=mm2=0; 70 for(int i=1; i<=n; i++) 71 if(!dfn[i]) tarjin(i); 72 if(ans==1){printf("0\n");continue;} 73 for(int i=1;i<=m;i++) 74 { 75 x=b[from[i]],y=b[to[i]]; 76 if(x!=y) cntout[x]++,cntin[y]++; 77 } 78 for(int i=1;i<=ans;i++) 79 { 80 if(!cntin[i]) mm1++; 81 if(!cntout[i]) mm2++; 82 } 83 printf("%d\n",max(mm1,mm2)); 84 } 85 return 0; 86 }