hdu 3836 tarjain 求强连通分量个数

复制代码
  1 //  给你一个有向图,问你最少加几条边能使得该图强连通
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <string>
  6 #include <utility>
  7 #include <algorithm>
  8 #include <vector>
  9 #include <queue>
 10 #include <stack>
 11 using namespace std;
 12 #define max(x,y) x>=y?x:y
 13 #define lowbit(x) x&(-x)
 14 typedef  long long ll;
 15 const int  N=20010;
 16 int n,m;
 17 int head[N],low[N],num[N];
 18 int  in[N],out[N],be[N];
 19 int  ans,cnt,ans1,ans2;
 20 int  index;
 21 bool vis[N];
 22 struct Edge
 23 {
 24     int from,to,nex;
 25 }e[N*6];
 26 stack<int>s;
 27 void init()
 28 {
 29     memset(head,-1,sizeof(head));
 30     memset(num,-1,sizeof(num));
 31     memset(vis,0,sizeof(vis));
 32     memset(low,0,sizeof(low));
 33     memset(in,0,sizeof(in));
 34     memset(out,0,sizeof(out));
 35     cnt=index=0;    
 36 }
 37 void add(int u,int v)
 38 {
 39     e[cnt].from=u;
 40     e[cnt].to=v;
 41     e[cnt].nex=head[u];
 42     head[u]=cnt++;
 43 }
 44 void tarjan(int u)
 45 {
 46     low[u]=num[u]=++index;
 47     vis[u]=1;
 48     s.push(u);
 49     for (int i=head[u];i!=-1;i=e[i].nex)
 50     {
 51         int v=e[i].to;
 52         if(num[v]==-1)
 53         {
 54             tarjan(v);
 55             low[u]=min(low[u],low[v]);
 56         }
 57         else if(vis[v])
 58         {
 59             low[u]=min(low[u],num[v]);
 60         }
 61     }
 62     if(num[u]==low[u])
 63     {
 64         int x;
 65         ans++;
 66         do{
 67             x=s.top();
 68             s.pop();
 69             vis[x]=0;
 70             be[x]=ans;
 71         }while(x!=u);
 72     }
 73 }
 74 int main()
 75 {
 76     while(~scanf("%d %d",&n,&m))
 77     {
 78         init();
 79         ans=0;
 80         int a,b;
 81         for (int i=0;i<m;i++)
 82         {
 83             scanf("%d %d",&a,&b);
 84             add(a,b);
 85             
 86         }
 87         for (int i=1;i<=n;i++)
 88         {
 89             if(num[i]==-1)
 90             {
 91                 tarjan(i);
 92             }
 93         }
 94         for (int i=0;i<cnt;i++)
 95         {
 96             int a=e[i].from;
 97             int b=e[i].to;
 98             if(be[a]!=be[b])
 99             {
100                 in[be[b]]++;
101                 out[be[a]]++;
102             }
103         }
104         ans1=ans2=0;
105         for (int i=1;i<=ans;i++)//ans 从1开始。ans为原图强联通分量的个数、
106         {
107             if(!in[i])
108             {
109                 ans1++;
110             }
111             if(!out[i])
112             {
113                 ans2++;
114             }
115         }
116         printf("%d\n",ans==1?0:max(ans1,ans2));    
117     }
118     return 0;
119 }
120 
121 /*
122 
123 3 2
124 1 2
125 2 3
126 
127 有3个联通快
128 
129 */
复制代码

 

posted on   cltt  阅读(140)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示