Acwing 1174.受欢迎的牛(tarjan求有向图强连通分量 + 缩点)

简介: 笔记

Acwing 1174. 受欢迎的牛


题意

每一头牛的愿望就是变成一头最受欢迎的牛。

现在有 N头牛,编号从 1 到 N  ,给你 M 对整数(A,B) ,表示牛 A认为牛B 受欢迎。 这种关系是具有传递性的,如果A 认为 B 受欢迎,B 认为 C 受欢迎,那么牛 A 也认为牛C 受欢迎。 你的任务是求出有多少头牛被除自己之外的所有牛认为是受欢迎的。


思路

先用tarjan算法求出强连通分量并缩点,缩点后构成一个有向无环图(DAG),如果这个有向无环图的终点 – 即出度为 0 的点只有一个,则这个点是被所有牛认为是受欢迎的,输出这个强连通分量的大小即可,否则不存在受所有牛欢迎的牛


代码

const int N = 5e4 + 10, M = 5 * N;
int n, m;
int h[N], e[M], ne[M], idx;
int dfn[N], low[N];
int dout[N];
int scc, timestamp;
bool in_stk[N];
stack<int>stk;
int id[N], siz[N];
void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void tarjan(int u) {
    dfn[u] = low[u] = ++timestamp;
    stk.push(u), in_stk[u] = true;
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (!dfn[j]) {
            tarjan(j);
            low[u] = min(low[u], low[j]);
        }
        else if (in_stk[j]) {
            low[u] = min(low[u], dfn[j]);
        }
    }
    if (dfn[u] == low[u]) {
        int y = 0;
        ++scc;
        do {
            y = stk.top();
            stk.pop();
            in_stk[y] = false;
            id[y] = scc;
            siz[scc]++;
        } while (y != u);
    }
}
void solve() {
    scanf("%d%d", &n, &m);
    memset(h, -1, sizeof h);
    while (m--) {
        int u, v; scanf("%d%d", &u, &v);
        add(u, v);
    }
    for (int i = 1; i <= n; ++i) {
        if (!dfn[i])
            tarjan(i);
    }
    int cnt = 0;
    int res = 0;
    for (int i = 1; i <= n; ++i) {
        for (int j = h[i]; ~j; j = ne[j]) {
            int k = e[j];
            if (id[i] != id[k]) {
                dout[id[i]]++;
            }
        }
    }
    for (int i = 1; i <= scc; ++i) {
        if (!dout[i])cnt++, res = siz[i];
    }
    if (cnt == 1) cout << res << endl;
    else puts("0");
}
signed main() {
    //int _; cin >> _;
    //while (_--)
    solve();
    return 0;
}


目录
相关文章
|
算法
OR-tools求解器使用介绍(二)
OR-tools求解器使用介绍(二)
1591 0
|
JavaScript
vue3,使用watch监听props中的数据
【10月更文挑战第3天】
4027 2
|
前端开发
Canvas绘画之简单的多边形绘画
Canvas绘画之简单的多边形绘画
【C#编程最佳实践 十一】降低圈复杂度最佳实践
【C#编程最佳实践 十一】降低圈复杂度最佳实践
394 0
|
MySQL 关系型数据库 iOS开发
macOS使用django安装mysqlclient遇到的问题(mysqlclient 1.3.3 or newer is required)
以后博客更新在:https://oldpan.me 有两个月没有碰django了,没想到一下从11.3升级到了2.0。django框架团队真的是很用心。
4438 0
|
Web App开发 JavaScript 前端开发
|
Java 定位技术 API
Android高效率编码-第三方SDK详解系列(一)——百度地图,绘制,覆盖物,导航,定位,细腻分解!
<div class="markdown_views"> <h1 id="android高效率编码-第三方sdk详解系列一百度地图绘制覆盖物导航定位细腻分解">Android高效率编码-第三方SDK详解系列(一)——百度地图,绘制,覆盖物,导航,定位,细腻分解!</h1> <hr> <blockquote> <p>这是一个系列,但是我也不确定具体会更新多少期,最近很忙,主
6134 0
|
Linux C语言
Linux下C语言执行过程(预处理,编译,汇编,链接,执行)
1、C语言的执行过程包括5个步骤:分别是:预处理,编译,汇编,链接,执行 第一步:编写C源代码,截图如下: 2、预处理,命令为:gcc -E variable.c -o variable.i(这步的作用是文件的展开和宏替换),生成的文件类型是.i类型的。 3、编译:命令为:gcc -S variable.i -o variable.s,这里的.s文件就成了会变语言,截图如下:
1713 0