题目链接:http://poj.org/problem?id=2186

题目大意:

每头牛都想成为牛群中的红人。

给定N头牛的牛群和M个有序对(A, B),(A, B)表示牛A认为牛B是红人;

该关系具有传递性,所以如果牛A认为牛B是红人,牛B认为牛C是红人,那么牛A也认为牛C是红人。

不过,给定的有序对中可能包含(A, B)和(B, C),但不包含(A, C)。

求被其他所有牛认为是红人的牛的总数。

题目分析(引自 https://www.cnblogs.com/violet-acmer/p/9740737.html):

考虑以牛为顶点的有向图,对每个有序对(A, B)连一条从 A到B的有向边;

那么,被其他所有牛认为是红人的牛对应的顶点,也就是从其他所有顶点都可达的顶点。

虽然这可以通过从每个顶点出发搜索求得,但总的复杂度却是O(NM),是不可行的,必须要考虑更为高效的算法。

假设有两头牛A和B都被其他所有牛认为是红人,那么显然,A被B认为是红人,B也被A认为是红人;

即存在一个包含A、B两个顶点的圈,或者说,A、B同属于一个强连通分量。

反之,如果一头牛被其他所有牛认为是红人,那么其所属的强连通分量内的所有牛都被其他所有牛认为是红人。

由此,我们把图进行强连通分量分解后,至多有一个强连通分量满足题目的条件。

而按前面介绍的算法进行强连通分量分解时,我们还能够得到各个强连通分量拓扑排序后的顺序;

唯一可能成为解的只有拓扑序最后的强连通分量。

所以在最后,我们只要检查这个强连通分量是否从所有顶点可达就好了。

思路整理:

1、首先,使用tarjan缩点;

2、其次,检查是否所有点可达

只需要确定是不是缩点后只有一个点的出度为0即可。

如果只有一个点的出度为0,则答案为该点对应的强连通分量中的原图中的点的数量;

否则,答案为 0。

实现代码如下:

#include <iostream>
#include <vector>
#include <stack>
#include <cstring>
using namespace std;
const int maxn = 10010;
int n, dfn[maxn], low[maxn], belong[maxn], idx, cnt;
bool instk[maxn];
stack<int> stk;
vector<int> g[maxn];
void tarjan(int u) {
dfn[u] = low[u] = ++idx;
instk[u] = true;
stk.push(u);
int sz = g[u].size();
for (int i = 0; i < sz; i ++) {
int v = g[u][i];
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (instk[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
cnt ++;
int v;
do {
v = stk.top();
stk.pop();
instk[v] = false;
belong[v] = cnt;
} while (u != v);
}
}
void solve() {
memset(dfn, 0, sizeof(dfn));
memset(instk, 0, sizeof(instk));
for (int i = 1; i <= n; i ++) if (!dfn[i]) tarjan(i);
}
int m;
bool vis[maxn];
int main() {
cin >> n >> m;
while (m --) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
}
solve();
for (int u = 1; u <= n; u ++) {
int sz = g[u].size();
for (int i = 0; i < sz; i ++) {
int v = g[u][i];
if (belong[u] != belong[v]) {
vis[ belong[u] ] = true;
}
}
}
int cc = 0, id = -1;
for (int i = 1; i <= cnt; i ++) if (!vis[i]) {
cc ++;
id = i;
}
if (cc != 1) {
cout << 0 << endl;
return 0;
}
int ans = 0;
for (int i = 1; i <= n; i ++) if (belong[i] == id) ans ++;
cout << ans << endl;
return 0;
}

POJ2186 Popular Cows 题解 强连通分量的更多相关文章

  1. POJ2186 Popular Cows 题解 强连通分量入门题

    题目链接:http://poj.org/problem?id=2186 题目大意: 每头牛都想成为牛群中的红人. 给定N头牛的牛群和M个有序对(A, B),(A, B)表示牛A认为牛B是红人: 该关系 ...

  2. POJ2186 Popular Cows 【强连通分量】+【Kosaraju】+【Tarjan】+【Garbow】

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23445   Accepted: 9605 Des ...

  3. POJ2186 Popular Cows(强连通分量)

    题目问一个有向图所有点都能达到的点有几个. 先把图的强连通分量缩点,形成一个DAG,那么DAG“尾巴”(出度0的点)所表示的强连通分量就是解,因为前面的部分都能到达尾巴,但如果有多个尾巴那解就是0了, ...

  4. poj 2186 Popular Cows 【强连通分量Tarjan算法 + 树问题】

    题目地址:http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Sub ...

  5. poj2186 Popular Cows 题解——S.B.S.

    Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 29642   Accepted: 11996 De ...

  6. POJ 2186 Popular Cows(强连通分量)

    [题目链接] http://poj.org/problem?id=2186 [题目大意] 给出一张有向图,问能被所有点到达的点的数量 [题解] 我们发现能成为答案的,只有拓扑序最后的SCC中的所有点, ...

  7. poj 2186 "Popular Cows"(强连通分量入门题)

    传送门 参考资料: [1]:挑战程序设计竞赛 题意: 每头牛都想成为牛群中的红人. 给定N头牛的牛群和M个有序对(A, B),(A, B)表示牛A认为牛B是红人: 该关系具有传递性,所以如果牛A认为牛 ...

  8. POJ 2186 Popular Cows(强连通分量Kosaraju)

    http://poj.org/problem?id=2186 题意: 一个有向图,求出点的个数(任意点可达). 思路: Kosaraju算法的第一次dfs是后序遍历,而第二次遍历时遍历它的反向图,从标 ...

  9. poj2186 Popular Cows(强连通)

    崇拜有传递性.求所有牛都崇拜的牛tarjan算法求强连通. 如果不连通就不存在.如果联通,缩点后唯一一个出度为零的点就是答案,有多个则不存在. #include <vector> #inc ...

随机推荐

  1. 【[Offer收割]编程练习赛9 C】三等分

    [题目链接]:http://hihocoder.com/problemset/problem/1479 [题意] . [题解] 首先算出所有节点的权值的和val; 然后如果val%3!=0则直接输出0 ...

  2. Tyvj-1338 QQ农场

    P1338 QQ农场 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 Sandytea前段时间沉迷于QQ农场中……一天夜里,他梦见来到好友X的农场上…… 描述 ...

  3. 高级PHP开发:利用PHPEMS搭建在线考试平台

    今天给大家分享一个小技巧,就是利用PHP ems搭建在线考试平台:希望能给你给予帮助: 在给大家分享之前,这里推荐下我自己建的PHP开发-VIP资料出售平台 :638965404,不管你是小白还是大牛 ...

  4. 2016国产开源软件Top100(Q1)

    2016国产开源软件Top100(Q1) 随着互联网的发展.开放标准的普及和虚拟化技术的应用等诸多IT新领域的创新及拓展,开源技术凭借其开放性.低成本.稳定性.灵活性.安全性和技术创新性等特点迅速走向 ...

  5. python基础之包的导入

    包的导入 python是一门灵活性的语言 ,也可以说python是一门胶水语言,顾名思义,就是可一导入各类的包, python的包可是说是所有语言中最多的.当然导入包大部分是为了更方便,更简便,效率更 ...

  6. python -- 类中--内置方法

    isinstance 和  issubclass isinstance(obj,b)  检查是否obj是否是类b的对象 class A(object):pass class B(A):pass b=B ...

  7. Spring Boot 集成日志logback + 控制台打印SQL

    一: 控制台打印SQL application.properties中添加如下即可在控制台打印sql logging.level.com.fx.fxxt.mapper=debug 二:日志 因为Spr ...

  8. HDU 2717 宽搜第一题、

    题意:求n到k的最小路径,  n有三种变法 n+1,n-1或者2*n: 贴个广搜的模版在这里把.... 总结一下:一般涉及到求最短路的话用宽搜 #include<iostream> #in ...

  9. KMP未优化模板、

    要理解KMP最重要的一点就是防止重复的回溯. !!!很重要!!!很重要!!!很重要 要了解KMP可以去:http://www.cnblogs.com/dolphin0520/archive/2011/ ...

  10. Java内存分析工具--IDEA的JProfiler和JMeter插件

    一.JProfiler简介 JProfiler 是一个商业授权的Java剖析工具,由EJ技术有限公司,针对的Java EE和Java SE应用程序开发的.它把CPU.执行绪和内存的剖析组合在一个强大的 ...