把一个图变成任意两点可达需要添加边的条数

给你一个图最少添加几条边能使他任意两点可达:

有向图(连通图)

   找出入度为零的顶点的个数 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         

 

posted @ 2012-05-09 22:28  知行执行  阅读(307)  评论(0编辑  收藏  举报