题目链接: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. C函数和宏中的可变参数

    一:调用惯例 函数的调用方和被调用方对函数如何调用应该有统一的理解,否则函数就无法正确调用.比如foo(int n, int m),调用方如果认为压栈顺序是m,n,而foo认为压栈顺序是n, m,那么 ...

  2. Libev源码分析08:Libev中的内存扩容方法

    在Libev中,如果某种结构的数组需要扩容,它使用array_needsize宏进行处理,比如: array_needsize (int, fdchanges, fdchangemax, fdchan ...

  3. Jmeter正则表达式提取多个值示例

    首先了解一下常用正则表达式的语法 \d           数字 \w          数字或者字母 .             可以匹配任意字符 星号*     表示任意个字符  +       ...

  4. poj 3169 Layout (差分约束)

    3169 -- Layout 继续差分约束. 这题要判起点终点是否连通,并且要判负环,所以要用到spfa. 对于ML的边,要求两者之间距离要小于给定值,于是构建(a)->(b)=c的边.同理,对 ...

  5. iptables 限制访问规则

    iptables -I INPUT 1 -m state --state RELATED,ESTABLISHED -j ACCEPT把这条语句插在input链的最前面(第一条),对状态为ESTABLI ...

  6. Pytorch: 命名实体识别: BertForTokenClassification/pytorch-crf

    文章目录基本介绍BertForTokenClassificationpytorch-crf实验项目参考基本介绍命名实体识别:命名实体识别任务是NLP中的一个基础任务.主要是从一句话中识别出命名实体.比 ...

  7. Android ViewGroup点击效果(背景色)

    在开发Android应用的界面时,我们必然会用到本文ViewGroup,尤其是FrameLayout,LinearLayout,RelativeLayout等ViewGroup的子类: 在一些情况下, ...

  8. HDU 1875 最小生成树prim算法

    #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #inc ...

  9. WOE:信用评分卡模型中的变量离散化方法(生存分析)

    WOE:信用评分卡模型中的变量离散化方法 2016-03-21 生存分析 在做回归模型时,因临床需要常常需要对连续性的变量离散化,诸如年龄,分为老.中.青三组,一般的做法是ROC或者X-tile等等. ...

  10. laravel 是怎么做到运行 composer dump-autoload 不清空 classmap 映射关系的呢?

    我看 laravel 的 composer.json 文件 autoload 也没配置 vendor/autoload_classmap.php 里的映射关系,正常来说,如果没有配置,执行 compo ...