强联通 HDU 2767 3836

n个点m条边

最少需要几条边变成强连通图

设有a个结点的入读为0, b个结点的出度为0, 则 max{a, b}就是答案。 注意特殊情况: 当原图已经强连通时, 答案是0而不是1.

加一条边少一个入度出度

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<string.h>
  4 #include<queue>
  5 #include<math.h>
  6 #include<stack>
  7 
  8 using namespace std;
  9 
 10 #define MAXN 100010
 11 
 12 int head[MAXN],low[MAXN],dfn[MAXN],f[MAXN],in[MAXN],out[MAXN];
 13 bool vis[MAXN];
 14 int cnt,k,num;
 15 struct edg
 16 {
 17     int fr,to,next;
 18 
 19 }x[MAXN];
 20 
 21 void add(int u,int v)
 22 {
 23     x[cnt].next=head[u];
 24     x[cnt].fr=u;
 25     x[cnt].to=v;
 26     head[u]=cnt++;
 27 }
 28 stack<int>s;
 29 
 30 void dfs(int u)
 31 {
 32     low[u]=dfn[u]=k++;
 33     vis[u]=1;
 34     s.push(u);
 35     int i;
 36     for(i=head[u];i!=-1;i=x[i].next)
 37     {
 38         int t=x[i].to;
 39         if(!dfn[t])
 40         {
 41             dfs(t);
 42             low[u]=min(low[u],low[t]);
 43         }
 44         else if(vis[t])
 45             low[u]=min(low[u],dfn[t]);
 46     }
 47     if(low[u]==dfn[u])
 48     {
 49         num++;
 50         while(!s.empty())
 51         {
 52             int now=s.top();
 53             s.pop();
 54             vis[now]=0;
 55             f[now]=num;
 56             if(now==u)break;
 57         }
 58     }
 59 }
 60 
 61 int main()
 62 {
 63     int n,m,t;
 64 
 65     while(scanf("%d%d",&n,&m)!=EOF)
 66     {
 67         int i;
 68         memset(head,-1,sizeof(head));
 69         cnt=0;
 70         for(i=1;i<=m;i++)
 71         {
 72             int a,b;
 73             scanf("%d%d",&a,&b);
 74             add(a,b);
 75         }
 76         k=1;
 77         num=0;
 78         memset(dfn,0,sizeof(dfn));
 79         memset(low,0,sizeof(low));
 80         memset(vis,0,sizeof(vis));
 81         memset(f,0,sizeof(f));
 82         for(i=1;i<=n;i++)
 83         {
 84             if(!dfn[i])
 85                 dfs(i);
 86         }
 87         memset(head,-1,sizeof(head));
 88         int en=cnt;
 89         memset(in,0,sizeof(in));
 90         memset(out,0,sizeof(out));
 91 
 92         for(i=0;i<en;i++)
 93         {
 94             int u,v;
 95             u=f[x[i].fr];
 96             v=f[x[i].to];
 97             if(u!=v)
 98             {
 99                 add(u,v);
100                 out[u]++;
101                 in[v]++;
102             }
103         }
104         int a,b;
105         a=b=0;
106 
107         for(i=1;i<=num;i++)
108         {
109             if(in[i]==0)
110                 a++;
111             if(out[i]==0)
112                 b++;
113         }
114         if(num==1)
115             printf("0
");
116         else
117             printf("%d
",max(a,b));
118     }
119     return 0;
120 }
原文地址:https://www.cnblogs.com/cherryMJY/p/6058804.html