Popular Cows(POJ2186)(强连通+缩点)(Korasaju)
来源:互联网 发布:c语言逻辑表达式符号 编辑:程序博客网 时间:2024/06/14 21:05
题目:http://acm.hust.edu.cn/vjudge/problem/16578
抽象出来的题意:给定一个有向图,求有多少个顶点是由任何顶点出发都可达的。
题解:
1、有向无环图中唯一出度为0的点,一定可以由任何点出发均可达。
2、则现在的要求就变成了把图构造成有向无环图DAG,并计算无环图中每个点的出度。
若要构建有向无环图,就要把所有的环都缩成一个点,当把所有的环都缩成一个点以后,有向无环图就出现了。
3、那要如何找到所有的环呢。我们可以来看一下强连通的定义:图论中,强连通图指每一个顶点皆可以经由该图上的边抵达其他的每一个点的有向图。那对图求一下强连通分量(可以参考满天飞的模板,我这里用的是kuangbin的Korasaju算法模板),每一个强连通分量不就是一个环么,把所有强连通分量缩成一个环,DAG就出现了。
4、如何缩点。开一个Belong数组,把所有属于同一个强连通分量的点标记成一个数字,这样就类似于缩点了。
5、计算出度方法
int de[maxn];memset (de, 0, sizeof(de));for (int i = 1; i <= m; i++) { if (Belong[e[i].l] != Belong[e[i].r]) { de[Belong[e[i].l]]++; }}
思考:
1、有向无环图中唯一出度为0的点,一定可以由任何点出发均可达
2、因为要构造有向无环图DAG,则把每个强连通分量缩成一点
3、缩点的时候不一定要构造新图,只要把不同强连通分量的点染不同颜色,然后考察各种颜色的点有没有连到别的颜色的边即可
#include <iostream>#include <cstdio>#include <string>#include <algorithm>#include <cstring>#include <cmath>#include <vector>#include <map>#include <set>#include <queue>using namespace std;const int maxm = 50010;const int maxn = 10010;struct Edge{ int l, r;}e[maxm];struct Node{ int to, next;}edge1[maxm], edge2[maxm];int head1[maxn], head2[maxn];bool mark1[maxn], mark2[maxn];int tot1, tot2;int cnt1, cnt2;int st[maxn];int Belong[maxn];int num;int SetNum[maxn];void addedge(int u, int v){ edge1[tot1].to = v; edge1[tot1].next = head1[u]; head1[u] = tot1++; edge2[tot2].to = u; edge2[tot2].next = head2[v]; head2[v] = tot2++;}void DFS1(int u){ mark1[u] = true; for (int i = head1[u]; i != -1 ;i = edge1[i].next) { if (!mark1[edge1[i].to]) DFS1( (edge1[i].to)); } st[cnt1++] = u;}void DFS2(int u){ mark2[u] = true; num++; Belong[u] = cnt2; for (int i = head2[u]; i != -1; i = edge2[i].next) if (!mark2[edge2[i].to]) DFS2 (edge2[i].to);}void solve(int n){ memset (mark1 ,false, sizeof(mark1)); memset (mark2, false, sizeof(mark2)); cnt1 = cnt2 = 1; for (int i = 1; i <= n; i++) { if (!mark1[i]) DFS1 (i); } for (int i = cnt1 - 1; i >= 1; i--) { if (!mark2[st[i]]) { num = 0; DFS2 (st[i]); SetNum[cnt2++] = num; } }}int main(){ #ifndef ONLINE_JUDGE freopen ("in.txt", "r", stdin); #endif // ONLINE_JUDGE int n, m; scanf ("%d%d", &n, &m); tot1 = tot2 = 1; for(int i = 1; i <= n; i++)//初始化 { head1[i] = head2[i] = -1; mark1[i] = mark2[i] = 0; } for (int i = 1; i <= m; i++) { int a, b; scanf ("%d%d", &a, &b); e[i].l = a; e[i].r = b; addedge (a, b); } solve (n); //计算出度 int de[maxn]; memset (de, 0, sizeof(de)); for (int i = 1; i <= m; i++) { if (Belong[e[i].l] != Belong[e[i].r]) { de[Belong[e[i].l]]++; } } int cnt = 0, res; for (int i = 1; i < cnt2; i++) { if (!de[i]) { cnt++; res = i; } } if (cnt > 1) printf ("0\n"); else printf ("%d\n", SetNum[res]); return 0;}
0 0
- Popular Cows(POJ2186)(强连通+缩点)(Korasaju)
- POJ2186----Popular Cows(强连通+缩点)
- poj2186--Popular Cows(强连通+缩点)
- POJ2186 Popular Cows(强连通分量)
- poj2186 Popular Cows(强连通分量)
- POJ2186--Popular Cows(Korasaju+缩点)
- poj2186 Popular Cows(强连通分量)(korasaju||tarjan模板题)
- 图论:POJ2186-Popular Cows (求强连通分量)
- poj2186 Popular Cows(tarjan + 缩点)
- POJ2186--Popular Cows(Tarjan+缩点)
- poj2186 Popular Cows--Kosaraju算法 & 缩点 & 强连通分量
- 【2186】Popular Cows(强连通分支及其缩点)
- Popular Cows poj 2186(强连通分量+缩点 )
- POJ 2186 Popular Cows(korasaju Algorithm求强连通分量)
- poj2186 Popular Cows --- 强连通
- poj2186 Popular Cows【强连通】
- 【POJ2186】Popular Cows 有向图强连通分量详解(再水一篇怕被骂、、所以。。)
- POJ2186 Popular Cows 强连通 Tarjan
- Android Studio for Ubuntu 14.04 无法输入中文解决办法
- Spring mvc的单例和多例性能
- 电商网页布局+动态实现
- enable_shared_from_this模板类使用完全解析
- 一个API设计工具——Swagger,将如何帮助我们更好的实现“前后端分离”
- Popular Cows(POJ2186)(强连通+缩点)(Korasaju)
- tomcat部署weblogic服务器项目到本地执行的总结整理
- PHP常用字符串函数详解
- 写在前面
- ThinkPHP中同时上传视频和图片的简单处理方法
- cocos2djs游戏android sdk接入
- 2behavior原理解析
- RGB24转yuv420 高效率 且颜色没有失真
- HTML5分组元素(20160804-0004)