poj2186 求有向图G中所有点都能到达的点的数量
来源:互联网 发布:中国少儿编程网scratch 编辑:程序博客网 时间:2024/05/16 09:52
/*题意:有向图,求这样的点的数量:所有点都能到达它.缩点成有向无环图,思:如果该强连通有出度,那么从该出度出去的边必然回不来(已经缩点了),所以有出度的强连通必然不是。那么是不是所有出度为0的强连通分量都是呢?显然不是,如果存在多个出度为0的强连通,他们必然无解(他们之间必然不连通)。任然遍历边,判断不在一个连通分量中的边(即为缩点后的边)和点,考察期出度即可。*/#include<iostream> //329ms,1A,基础题。#include<vector>#include<cstdio>#include<cstring>#include<stack>#include<queue>using namespace std;int n;int m;const int MAX=10001;vector<vector<int> >edges(MAX);int visited[MAX];int low[MAX];int dfn[MAX];bool has_outd[MAX]; //是否有出度int Strongly_connected_branch[MAX]; //并为一个强连通,标记为1.2.3...int num;int times; bool is_popular[MAX]; //整个强连通分支i是否有出度,其中一个点有即有stack<int>s; bool instack[MAX];int num_of_popular; //统计最终数量void tarjan(int u){ low[u]=dfn[u]=times++; instack[u]=1; s.push(u); int len=edges[u].size(); for(int i=0;i<len;i++) { int v=edges[u][i]; if(visited[v]==0) { visited[v]=1; tarjan(v); if(low[u]>low[v])low[u]=low[v]; } else if(instack[v]&&low[u]>dfn[v]) //有向图,要问是否在栈中,后向边,V为U某个祖先 { low[u]=dfn[v]; } } if(dfn[u]==low[u]) //在一个SCC { num++;int temp; do { temp=s.top(); instack[temp]=0; s.pop(); Strongly_connected_branch[temp]=num; } while(temp!=u); }}void initialize() //初始化{ num_of_popular=num=times=0; for(int i=0;i<=n;i++) { has_outd[i]=instack[i]=low[i]=dfn[i]=visited[i]=0; edges[i].clear(); is_popular[i]=1; Strongly_connected_branch[i]=-1; }}bool readin(){ scanf("%d",&n); scanf("%d",&m); initialize(); int from,to; for(int i=1;i<=m;i++) { scanf("%d%d",&from,&to); edges[from].push_back(to); } return 1;}void solve(){ for(int i=1;i<=n;i++) if(visited[i]==0) { visited[i]=1; tarjan(i); } for(int i=1;i<=n;i++) //自己思得:枚举所有边,缩点只是把所有SCC分开 { int len=edges[i].size(); for(int j=0;j<len;j++) { int v=edges[i][j]; if(Strongly_connected_branch[v]!=Strongly_connected_branch[i])//不在用一个强连通分支 { has_outd[i]=1; //i所在强连通分量有出度 is_popular[Strongly_connected_branch[i]]=0; //其所在强连通全跪! break; } } } queue<int>q; for(int i=1;i<=n;i++) //统计期所在强连通出度为0的点 { if(is_popular[Strongly_connected_branch[i]]==0){continue;} if(has_outd[i]==0)q.push(i); } int te=Strongly_connected_branch[q.front()]; while(!q.empty()) //判断他们是否都在一个强连通中,否则跳出,无解。 { int cur=q.front(); if(te!=Strongly_connected_branch[cur]){printf("0\n");return;} num_of_popular++; q.pop(); te=Strongly_connected_branch[cur]; } printf("%d\n",num_of_popular);}int main(){ readin(); solve(); return 0;}
0 0
- poj2186 求有向图G中所有点都能到达的点的数量
- poj 2186 (求一个图中可以到达所有点的点的个数) (强连通)
- poj 2186 Popular Cows 【有向图求SCC +缩点】【求图中有多少个点 可以由其余所有点通过存在路径到达】
- 图论算法(2)--- 如何求DAG中每一个点的所有子孙数量
- 求一个有向图G的拓扑序列
- poj2186 有向图强连通缩点
- poj1523—SPF(tarjan算法求无向图中所有的割点)
- poj 2125 有向图破坏,求拆掉图中所有边的最小代价
- 有向图中以一个顶点为起始点的所有路径
- 39 求一个有向连通图的割点
- 求一无向图G中所有环
- hdoj 1827 Summer Holiday 【有向图 连通最少的点来间接连通所有点】 【tarjan求 SCC + 缩点】
- 有向图的强连通分量的分解 总结 poj2186例题举例
- 给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数---矩阵乘法
- 有向图中打印所有的环路
- 求无向图中桥的数量 强连通图
- hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径
- Summer Holiday 【有向图中连通最少的点来使其整个图 连通的】+【tarjan求SCC +缩点】
- Cron 表达式详解和案例
- C#多态性基础实现
- 跨进程API Hook
- Tbitmap
- 折半查找 binary search
- poj2186 求有向图G中所有点都能到达的点的数量
- CloudStack与OpenStack的区别
- Strust2学习笔记
- linux下拷贝文件
- Spring定时器Quartz
- 1.ios编程所需要的条件和环境
- Cocos2d-x 按钮 CCControlButton 的 用法
- 关于为什么要写技术博客的思考
- git的安装与使用