• Poj 2186 Popular Cows (Tarjan)


    题目链接:

      Poj 2186 Popular Cows

    题目描述:

      有n只牛,牛之间存在一些关系,比如a认为b很受欢迎,b认为c很受欢迎,这样呢,a也会认为c很受欢迎,问根据给出的关系,有多少头牛被其他所有的牛都认为是受欢迎的?

    解题思路:

      对于一个有向无环图来说,其中有且仅有一个点出度为零,那么这个特殊的点,可以由其他任何点到达。那么接下来我们直接对所给的图进行强连通分量划分,然后把每个强连通分量看做一个点,判定出度为零的点有几个,如果有一个就输出这个点对应的强连通分量含有的节点个数,否则为零。

      1 #include <cstring>
      2 #include <cstdio>
      3 #include <string>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 const int maxn = 10005;
      8 struct node
      9 {
     10     int to, next;
     11 } edge[maxn*5];
     12 int head[maxn], id[maxn], tot, cnt, time, top;
     13 int dfn[maxn], low[maxn], vis[maxn], stack[maxn], instack[maxn];
     14 
     15 void init()
     16 {
     17     tot = top = 0;//top指向栈顶
     18     cnt = 0;//强连通分量
     19     time = 1;//时间戳
     20     memset (id, 0, sizeof(id));//i所属的连通分量
     21     memset (stack, 0, sizeof(stack));//dfs到的元素进栈
     22     memset (instack, 0, sizeof(instack));//i是否在栈中
     23     memset (head, -1, sizeof(head));
     24     memset (dfn, 0, sizeof(dfn));//进栈时间
     25     memset (low, 0, sizeof(low));//i能到达的最早进栈的节点的进栈时间
     26     memset (vis, 0, sizeof(vis));//强连通分量是否有出度
     27 }
     28 void Add (int from, int to)
     29 {
     30     edge[tot].to = to;
     31     edge[tot].next = head[from];
     32     head[from] = tot++;
     33 }
     34 void Tarjan (int u)
     35 {
     36     dfn[u] = low[u] = time ++;
     37     instack[u] = 1;
     38     stack[top++] = u;
     39     for (int i=head[u]; i!=-1; i=edge[i].next)
     40     {
     41         int v = edge[i].to;
     42         if (!dfn[v])//v没有dfs到过
     43             Tarjan(v);
     44         if (instack[v])//v在栈中
     45             low[u] = min (low[v], low[u]);
     46     }
     47     if (low[u] == dfn[u])
     48     {//找到一个强连通分量
     49         cnt ++;
     50         while (1)
     51         {//在栈中弹出强连通分量
     52             int v = stack[--top];
     53             instack[v] = 0;
     54             id[v] = cnt;
     55             if (v == u)
     56                 break;
     57         }
     58     }
     59 }
     60 
     61 int main ()
     62 {
     63     int n, m;
     64     while (scanf ("%d %d", &n, &m) != EOF)
     65     {
     66         init ();
     67         while (m --)
     68         {
     69             int from, to;
     70             scanf ("%d %d", &from, &to);
     71             Add (from, to);
     72         }
     73         for (int i=1; i<=n; i++)
     74             if (!dfn[i])//i点没进过栈,i点进栈继续dfs
     75                 Tarjan(i);
     76         int sum = 0, x;
     77         for (int i=1; i<=n; i++)
     78             for (int j=head[i]; j!=-1; j=edge[j].next)
     79                 if (id[i] != id[edge[j].to])//id[i] 到 id[edge[j].to这条边不在强连通分量中,记录id[i]分量有出度
     80                     vis[id[i]] ++;
     81         for (int i=1; i<=cnt; i++)
     82             if (!vis[i])
     83             {
     84                 sum ++;
     85                 x = i;
     86             }
     87 
     88         if (sum == 1)
     89         {
     90             sum = 0;
     91             for (int i=1; i<=n; i++)
     92                 if (id[i] == x)
     93                     sum ++;
     94             printf ("%d
    ", sum);
     95         }
     96         else
     97             printf ("0
    ");
     98     }
     99     return 0;
    100 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    idea2021.2安装后不能打开如何解决?(附无限试用方法)
    Linux驱动实践:一起来梳理中断的前世今生(附代码)
    Linux驱动实践:带你一步一步编译内核驱动程序
    Linux驱动实践:驱动程序如何发送【信号】给应用程序?
    Linux驱动实践:如何编写【 GPIO 】设备的驱动程序?
    Linux驱动实践:你知道【字符设备驱动程序】的两种写法吗?
    【无源物联网】物联网的下一个风口?
    分辨率并不是越高越好,因为人眼分辨能力存在极限
    如何判断一个哈希函数的好坏
    常用设计模式单例模式
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4660973.html
Copyright © 2020-2023  润新知