思路:找出出度为0 的顶点,如果出度为0的顶点大于1,则解为零,否则解就是出度为零的顶点的连通分支数。
刚开始是没有理解这道题的,也是看了大神之后才理解的。

方法一:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
using namespace std;
const int maxx=20005;
const int inf=0x3f3f3f3f;
int low[maxx];
int dfn[maxx];
int vis[maxx];
int flag[maxx];
int blong[maxx];//记录这个节点属于哪个强连通分量
int indegree[maxx];//记录入度
int outdegree[maxx];//记录出度
int index;
int tcost[maxx];
int root;
int num[maxx];
int ans;//记录强连通分量的个数
int n,m;
int head[maxx];
stack<int>s;
vector<int>G[maxx];
struct node{int u,v;int next;
}e[maxx];
void add(int u,int v,int i){e[i].u=u;e[i].v=v;e[i].next=head[u];head[u]=i;
}
void dfs(int u){index++;low[u]=dfn[u]=index;s.push(u);vis[u]=1;for(int i=0;i<G[u].size();i++){int v=G[u][i];if(dfn[v]==0){dfs(v);low[u]=min(low[u],low[v]);}else if(vis[v]==1){low[u]=min(low[u],dfn[v]);}}if(dfn[u]==low[u]){ans++;int v;do{v=s.top();s.pop();num[ans]++;blong[v]=ans;vis[v]=0;}while(u!=v);}
}
void init(){ans=0;memset(head,-1,sizeof(head));memset(flag,0,sizeof(flag));memset(num,0,sizeof(num));memset(vis,0,sizeof(vis));memset(low,0,sizeof(low));memset(dfn,0,sizeof(dfn));memset(blong,0,sizeof(blong));memset(indegree,0,sizeof(indegree));memset(outdegree,0,sizeof(outdegree));while(!s.empty())s.pop();for(int i=0;i<=n;i++){G[i].clear();}
}
int main(){while(scanf("%d %d",&n,&m)!=EOF){init();for(int i=1;i<=m;i++){int a,b;scanf("%d %d",&a,&b);G[a].push_back(b);}index=1;for(int i=1;i<=n;i++){if(dfn[i]==0){dfs(i);}}for(int i=1;i<=n;i++){for(int j=0;j<G[i].size();j++){int v=G[i][j];if(blong[i]!=blong[v]){outdegree[blong[i]]++;}}}int ans1=0;int loc=1;for(int i=1;i<=ans;i++){if(outdegree[i]==0){ans1++;loc=i;}}if(ans1!=1){cout<<0<<endl;}else{ans1=0;for(int i=1;i<=n;i++){if(outdegree[blong[i]]==0){ans1++; }}cout<<ans1<<endl;}}return 0;
}

Kosaraju算法:
算法思路:
步骤1:对正向图(原图)进行dfs求解得到正向图中各节点的拓扑序并且存在数组vs中。
步骤2:得到拓扑序之后,对反向图按照逆拓扑序进行rdfs,每次rdfs都得到一个强连通分量。
注意:在进行第一步的dfs之后,将数组vis清空。

注解:Map数组记录正向图,rMap数组记录反向图,flag数组标记属于哪个连通分量,vis数组标记访问情况,vs数组记录拓扑序。

方法二:Kosaraju算法
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
const int maxx=20005;
const int inf=0x3f3f3f3f;
vector<int>Map[maxx],rMap[maxx],vs;
int vis[maxx];
int n,m;
int flag[maxx];
int sum[maxx];
int indegree[maxx];
int outdegree[maxx];
int ans;
void init(){ans=0;memset(sum,0,sizeof(sum));memset(indegree,0,sizeof(indegree));memset(outdegree,0,sizeof(outdegree));memset(vis,0,sizeof(vis));memset(flag,0,sizeof(flag));for(int i=0;i<=n;i++){rMap[i].clear();Map[i].clear();}vs.clear();
}
void dfs(int v){vis[v]=1;for(int i=0;i<Map[v].size();i++){int t=Map[v][i];if(vis[t]==0){dfs(t);}}vs.push_back(v);
}
void rdfs(int v,int k){vis[v]=1;flag[v]=k;//v代表属于k这个连通分量 sum[k]++;for(int i=0;i<rMap[v].size();i++){int t=rMap[v][i];if(vis[t]==0){rdfs(t,k);}}
}
void solve(){for(int i=1;i<=n;i++){if(vis[i]==0){dfs(i);}}memset(vis,0,sizeof(vis));for(int i=vs.size()-1;i>=0;i--){if(vis[vs[i]]==0){ans++;rdfs(vs[i],ans);}}
}
int main(){int count=1;while(scanf("%d %d",&n,&m)!=EOF){init();for(int i=1;i<=m;i++){int a,b;scanf("%d %d",&a,&b);Map[a].push_back(b);rMap[b].push_back(a);}solve();for(int i=1;i<=n;i++){for(int j=0;j<Map[i].size();j++){int t=Map[i][j];if(flag[t]!=flag[i]){outdegree[flag[i]]++;indegree[flag[t]]++;}}}int ans1=0;for(int i=1;i<=ans;i++){if(outdegree[i]==0){ans1++;}}if(ans1!=1){cout<<0<<endl;}else{ans1=0;for(int i=1;i<=n;i++){if(outdegree[flag[i]]==0){ans1++;}}cout<<ans1<<endl;}}return 0;
}

poj2186(强连通分量)相关推荐

  1. poj2186(强连通分量分解)

    题目大概意思为有 N 头牛,有些牛认为有些牛是红人,该关系具有传递性,例如果牛A觉得牛B是红人,牛B认为牛C是红人,则牛A也会认为牛C是红人,求被其他所有牛认为是红人的牛的总数 假设被其他所有牛认为是 ...

  2. POJ2186——并查集+Tarjan算法求强连通分量

    算法讨论:这题陷阱比较多.首先,被所有牛欢迎,这说明所有的牛都要在一个连通图中,也就是将所给的边看成无向边的时候,所有点要在一个连通图中.这个我们用并查集来实现就可以了.强连通分量的求法就很简单了,正 ...

  3. POJ2186 Popular Cows【Tarjan】【强连通分量】

    题目连接: http://poj.org/problem?id=2186 题目大意: 每头奶牛都希望自己成为最欢迎的那头牛.给你N头牛,M个崇拜关系(A,B).意思是牛A 崇拜牛B.特别是,如果牛A崇 ...

  4. 有向图——强连通分量

    有向图的强连通分量(strongly connected components) 在有向图G中,如果两个顶点vi,vj间(vi!=vj)有一条从vi到vj的路径,同时还有一条从vj到vi的路径(顶点相 ...

  5. 【C++】强连通分量

    强连通分量 先来一题例题 题目大意 怎么做? 分析 结论 不要高兴得太早 怎么办呢? 定义 缩点法 原图构建新图 发现 新的结论 强连通分量算法 Kosaraju算法 Tarjan算法 例题:信息传递 ...

  6. 极小连通子图和极大连通子图_强连通分量与拓扑排序

    前言 由于GacUI里面开始多处用上拓扑排序,我决定把之前瞎JB搞出来的算法换掉,换成个正式的.之前我自己弄了个写起来很简单的算法,然后每一处需要用到的地方我就重新做一遍.当然这样肯定也是不行的,我觉 ...

  7. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...

    转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...

  8. HDU4635(强连通分量+Kosaraju算法)

    题意:给出一个有向图,最多添加多少条边使这个图依然不是强连通图:当这个图是强连通图时,输出-1: 求解思路:强连通分量求解: 强连通图:在有向图中,任意节点除法都可以到达其余所有节点,则称为强连通图. ...

  9. poj3352(强连通分量)

    题意:添加多少边才能使这个无向图为双连通分量. 注意:双连通分量适用于无向图:而强连通分量适用于有向图.但是这两个概念都是一样的. #include<iostream> #include& ...

最新文章

  1. Python错误:AttributeError: 'generator' object has no attribute 'next'解决办法
  2. 提权函数之RtlAdjustPrivilege()
  3. 鸿蒙系统正式版官方下载,华为鸿蒙os2.0系统app正式版
  4. NAB 2019见闻:CAE视频编码与QoE
  5. 【 .NET Core 3.0 】框架之二 || 后端项目搭建
  6. Python常见设计模式
  7. java manager 如何使用_java – Android:如何使用AlarmManager
  8. dao-service-servlet-jsp构建简易web通讯录(三层开发)知识点1
  9. docker之快速部署gogs git
  10. IQueryable和IEnumerable,IList的区别
  11. hadoop程序MapReduce之DataSort
  12. java中简单的删除添加修改_教你数据库简单实现添加,显示,修改,删除的方法
  13. 【Robot 学习1】 机器人平台搭建
  14. 西宁公交调度员招聘计算机题库,调度员考试题库.doc
  15. z变换解差分方程例题_Z变换及差分方程的求解
  16. 双拼输入法学习-搜狗方案-3
  17. 低碳节能智慧路灯杆解决方案
  18. PHP海补知识(6)-- nl2br/ucfirst/ucwords
  19. Ethercat 从站开发总结一:协议总结
  20. 解决华为云服务器没有公网Ip无法上网问题

热门文章

  1. Linux CENTOS7 Linux网络性能测试工具-iperf 安装过程以及示例!
  2. 链表问题5——反转部分单向链表
  3. 圆桌讨论:Cloud 2.0时代的工业互联网与智能制造
  4. 智在生活 自在慵懒 科沃斯机器人X京东大牌秒杀日主题展亮相无锡
  5. Zabbix安装配置(CentOS7.3)
  6. “安全即代码”:整合安全团队和DevOps团队
  7. checkstyle安装使用
  8. 奕新集团--RAC环境后续
  9. Postfix(一):CentOS 下安装postfix
  10. 小shell脚本---查找目录下面包含string的文件