把一个图变成任意两点可达需要添加边的条数
给你一个图最少添加几条边能使他任意两点可达:
有向图(连通图)
找出入度为零的顶点的个数 m
找出出度为零的顶点的个数 n
则需要添加的边数为:max(m,n);
例题:NYOJ 120
猜测:强连通缩点可以用来求有几个环
以下是NYOJ 120题用强连通缩点做的,改变后用来求环:
View Code
1 /*可以用来求环数*/ 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 #define MA 110 7 8 int M,num,head[MA],res,tops,inde; 9 int flag[MA],low[MA],dfn[MA],stack[MA]; 10 int cir=0; 11 12 struct point{ 13 int v,next; 14 }po[10010]; 15 16 void insert(int u,int v) 17 { 18 po[num].v=v; 19 po[num].next=head[u]; 20 head[u]=num++; 21 } 22 23 void dfs(int u) 24 { 25 int j; 26 low[u]=dfn[u]=inde++; 27 stack[++tops]=u; 28 flag[u]=1; 29 for(int i=head[u];i!=-1;i=po[i].next) 30 { 31 j=po[i].v; 32 if(!dfn[j]) 33 { 34 dfs(j); 35 low[u]=min(low[u],low[j]); 36 } 37 else if(flag[j])//不为零说明找到了一个环 38 { 39 low[u]=min(low[u],low[j]); 40 cir++; 41 } 42 } 43 44 if(low[u]==dfn[u])//释放环 45 { 46 res++; 47 do{ 48 j=stack[tops--]; 49 flag[j]=0; 50 }while(j!=u); 51 } 52 53 } 54 55 void tarjan() 56 { 57 for(int i=1;i<=M;i++) 58 if(!dfn[i]) 59 dfs(i); 60 } 61 62 int main() 63 { 64 int t,v; 65 scanf("%d", &t); 66 while(t--) 67 { 68 memset(flag,0,sizeof(flag)); 69 memset(low,0,sizeof(low)); 70 memset(dfn,0,sizeof(dfn)); 71 memset(head,-1,sizeof(head)); 72 scanf("%d",&M); 73 num=0; 74 res=0; 75 // top=0; 76 inde=1; 77 cir=0; 78 for(int i=1;i<=M;i++) 79 { 80 while(scanf("%d",&v)&&v) 81 insert(i,v); 82 } 83 tarjan(); 84 cout<<res-1<<endl; 85 cout<<"cir="<<cir<<endl; 86 } 87 return 0; 88 } 89 90 91