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\n", sum);
 95         }
 96         else
 97             printf ("0\n");
 98     }
 99     return 0;
100 }
时间: 2024-08-06 12:31:43

Poj 2186 Popular Cows (Tarjan)的相关文章

POJ 2186 Popular Cows -- tarjan 缩点

链接: POJ 2186 Popular Cows 题意: 每一头牛都希望在牛群里面备受瞩目,在一个牛群中有N头牛(1<=N<=10000),你被给予M(1<=M<=50000)个关系对,形式如(A,B),这意味着A牛认为B牛比它更受欢迎,由于这种欢迎度是满足传递性的,那么若是A牛认为B牛更受欢迎,B牛认为C牛更受欢迎,那么A牛也会认为C牛更受欢迎.你的任务是计算出被所有牛受欢迎的牛的个数. 输入: 第一行两个整数 N 和 M 第2 到 M + 1 行,两个分开的数 A,B,意味着

Poj 2186 Popular Cows(Tarjan 强连通缩点)

传送门:Poj 2186 题意:给你n头牛,m种关系,A牛认为B牛是popular的,B牛认为C牛是popular的,则A也认为C是popular的,问最终有几头被所有牛认为是popular的牛 题解:强连通缩点基础题(虽然我Tarjan和缩点都是对的,但是最终讨论判断的时候写垮了(写了3天....还不是你懒!!!!过年划水这么多天缩点后找出度为零的点个数.然后讨论是否有这样子的点,如果没有则全都是(整个都是强连通图),如果只有一个,那么那个强连通分量所含的牛的个数就是所求解,如果有多个那么都是

POJ 2186 Popular Cows tarjan缩点算法

题意:给出一个有向图代表牛和牛喜欢的关系,且喜欢关系具有传递性,求出能被所有牛喜欢的牛的总数(除了它自己以外的牛,或者它很自恋). 思路:这个的难处在于这是一个有环的图,对此我们可以使用tarjan算法求出强连通分量,把强连通分量压缩成一个点,构成一个新的图,这个图一定是没有环的,如果有环就跟强连通分量的矛盾了.压缩成无环图以后这个图里面的点是不具有方向的,我们通过遍历每个节点所能连到的点,如果两点的id值即所在的强连通分量区域不同时,我们就把这个节点的出度加1.最后去找那些出度等于0的点,如果

POJ 2186 Popular Cows --强连通分量

题意:给定一个有向图,问有多少个点由任意顶点出发都能达到. 分析:首先,在一个有向无环图中,能被所有点达到点,出度一定是0. 先求出所有的强连通分支,然后把每个强连通分支收缩成一个点,重新建图,这样,这个有向图就变成了一个有向无环图. 在这个新的图中,只需知道出度为0的点有几个即可. 如果出度为0的点超过1个,则输出0:否则输出出度为0的点所代表的那个强连通分支的分量数即可. 用Tarjan求强连通分量 代码: #include <iostream> #include <cstdio&g

poj 2186 Popular Cows 【强连通】

题目:poj 2186 Popular Cows 题意:n头牛,其中存在一些牛相互崇拜,具有传递性,问有多少头牛是被其他所有牛崇拜的. 分析:建立一个有向图,然后强连通缩点,之后求出度为0的点,假如存在多个,那么ans = 0,因为缩点之后如果x崇拜y,x也崇拜z,那么肯定y和z不能互相崇拜,不满足. 然后求出度为0的这个点缩点前环上有多少个点就ans AC代码: #include <cstdio> #include <vector> #include <iostream&g

POJ 2186 Popular Cows (强连通分量)

POJ 2186 Popular Cows 链接:http://poj.org/problem?id=2186 题意:每头奶牛都梦想着成为牧群中最受奶牛仰慕的奶牛.在牧群中,有N 头奶牛,1≤N≤10,000,给定M 对(1≤M≤50,000)有序对(A, B),表示A 仰慕B.由于仰慕关系具有传递性,也就是说,如果A 仰慕B,B 仰慕C,则A 也仰慕C,即使在给定的M 对关系中并没有(A, C).你的任务是计算牧群中受每头奶牛仰慕的奶牛数量. 思路:首先可以知道,在同一个强连通分量内的点一定互

强连通分量分解 Kosaraju算法 (poj 2186 Popular Cows)

poj 2186 Popular Cows 题意: 有N头牛, 给出M对关系, 如(1,2)代表1欢迎2, 关系是单向的且可以传递, 即1欢迎2不代表2欢迎1, 但是如果2也欢迎3那么1也欢迎3. 求被所有牛都欢迎的牛的数量. 限制: 1 <= N <= 10000 1 <= M <= 50000 思路: Kosaraju算法, 看缩点后拓扑序的终点有多少头牛, 且要判断是不是所有强连通分量都连向它. Kosaraju算法,分拆完连通分量后,也完成了拓扑序. /*poj 2186

poj 2186 Popular Cows 【强连通分量Tarjan算法 + 树问题】

题目地址:http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27496   Accepted: 11059 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows

POJ 2186 Popular Cows (强联通)

id=2186">http://poj.org/problem? id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23819   Accepted: 9767 Description Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <=