题目链接: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. [***]HZOJ 奇袭

    C. 奇袭 题目描述 由于各种原因,桐人现在被困在Under World(以下简称UW)中,而UW马上 要迎来最终的压力测试——魔界入侵. 唯一一个神一般存在的Administrator被消灭了,靠原 ...

  2. Java中Map/List/Set .

    很实用,分享一下. 简单版本 复杂版本 参考: http://initbinder.com/articles/cheat-sheet-for-selecting-maplistset-in-java. ...

  3. @noi.ac - 442@ 牛羊被他抢了

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 众所周知小G热衷于搏弈,有一天他来到你的大草原上,抢走了你所有的 ...

  4. input标签前台实现文件上传

    值得注意的是:当一个表单里面包含这个上传元素的时候,表单的enctype必须指定为multipart/form-data,method必须指定为post,浏览器才会认识并正确执行.但是还有一点,浏览器 ...

  5. 只要是使用函数file_get_contents访问 https 的网站都要开启

    使用file_get_contents();报错failed to open stream: Unable to find the socket transport "ssl" - ...

  6. 数据采集之js埋点

    一.后台nginx环境搭建 web点数据采集后台配置nginx:https://blog.csdn.net/weixin_37490221/article/details/80894827 下载数据源 ...

  7. jq动画和停止动画

    使用jq 实现动画循环效果 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...

  8. TabHost选项卡的实现(一):使用TabActivity实现

    一. TabHost的基本开发流程 TabHost是一种非常实用的组件,可以很方便的在窗口上防止多个标签页,每个标签页相当于获得了一个外部容器相同大小的组件摆放区域. 我们熟悉的手机电话系统" ...

  9. Python--day24--单继承关键字super

    super().  调用父类方法:(super不仅可以在一个类的内部使用,还可以在一个类的外部使用)

  10. SVN 树冲突解决详解

    https://blog.csdn.net/xgf415/article/details/75196714 SVN 冲突包括 内容冲突:当两名(或更多)开发人员修改了同一个文件中相邻或相同的行时就会发 ...