zoukankan      html  css  js  c++  java
  • [BZOJ1051] [HAOI2006] 受欢迎的牛 (强联通分量)

    Description

      每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
    种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
    牛被所有的牛认为是受欢迎的。

    Input

      第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可
    能出现多个A,B)

    Output

      一个数,即有多少头牛被所有的牛认为是受欢迎的。

    Sample Input

    3 3
    1 2
    2 1
    2 3

    Sample Output

    1

    HINT 

      100%的数据N<=10000,M<=50000

    Source

    Solution

      首先Tarjan缩点,那么一定有至少一个点没有出边。

      如果没有出边的点只有一个,那么其他点都直接或间接指向这个点。

      如果有多个,那么这几个无出边的点相互无边相连。

      答案就是该点表示的强联通分量里的点的个数。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 struct edge
     4 {
     5     int u, v, nxt;
     6 }e[100005];
     7 stack<int> S;
     8 int dfn[10005], low[10005], belong[10005], cnt1, cnt2;
     9 int ins[10005], fst[2][10005], outd[10005], siz[10005];
    10  
    11 void addedge(int i, int *x, int u, int v)
    12 {
    13     e[i] = (edge){u, v, x[u]}, x[u] = i;
    14 }
    15  
    16 void Tarjan(int u)
    17 {
    18     int v;
    19     dfn[u] = low[u] = ++cnt1;
    20     S.push(u), ins[u] = true;
    21     for(int i = fst[0][u]; i; i = e[i].nxt)
    22         if(!dfn[e[i].v])
    23         {
    24             Tarjan(e[i].v);
    25             low[u] = min(low[u], low[e[i].v]);
    26         }
    27         else if(ins[e[i].v])
    28             low[u] = min(low[u], low[e[i].v]);
    29     if(dfn[u] == low[u])
    30     {
    31         ++cnt2;
    32         do
    33         {
    34             v = S.top(), S.pop(), ins[v] = false;
    35             belong[v] = cnt2, ++siz[cnt2];
    36         }
    37         while(u != v);
    38     }
    39 }
    40  
    41 int main()
    42 {
    43     int n, m, u, v, ans = -1;
    44     cin >> n >> m;
    45     for(int i = 1; i <= m; ++i)
    46     {
    47         cin >> u >> v;
    48         addedge(i, fst[0], u, v);
    49     }
    50     for(int i = 1; i <= n; ++i)
    51         if(!dfn[i]) Tarjan(i);
    52     for(int i = 1; i <= m; ++i)
    53     {
    54         u = belong[e[i].u], v = belong[e[i].v];
    55         if(u != v)
    56         {
    57             addedge(i + m, fst[1], u, v);
    58             ++outd[u];
    59         }
    60     }
    61     for(int i = 1; i <= cnt2; ++i)
    62         if(!outd[i]) ans = ~ans ? 0 : siz[i];
    63     cout << ans << endl;
    64     return 0;
    65 }
    View Code

     

  • 相关阅读:
    2019.6.20刷题统计
    36 线程 队列 守护线程 互斥锁 死锁 可重入锁 信号量
    35 守护进程 互斥锁 IPC 共享内存 的方式 生产者消费者模型
    34 进程 pid ppid 并发与并行,阻塞与非阻塞 join函数 process对象 孤儿进程与僵尸进程
    33 udp 域名 进程
    32 粘包 文件传输
    31 socket客户端. 服务器 异常 语法
    30 网络编程
    29 元类 异常
    26 封装 反射 常用内置函数
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5551315.html
Copyright © 2011-2022 走看看