Popular Cows
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 31815   Accepted: 12927

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, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C is 
popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow. 

Input

* Line 1: Two space-separated integers, N and M

* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.

Output

* Line 1: A single integer that is the number of cows who are considered popular by every other cow. 

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

Hint

Cow 3 is the only cow of high popularity. 

Source

原题大意:给n头牛,m对形式(A,B)代表A觉得B很厉害,特殊的,如果A觉得B很厉害,B觉得C很厉害,那么A觉得C也很厉害,问有多少头牛被所有牛(除了它自己)觉得很厉害。
 
本题比较考验基础,涉及到链表,强连通分量的有关知识,对初学图论者还是有好处的。
 
解题思路:设n头牛中两两之间都觉得对方很厉害为一堆牛,而其中有一头牛被所有牛都认为很厉害,那么很显然,这堆牛都被所有牛认为很厉害。
              那会不会有两堆以上的牛都被所有人认为很厉害呢?显然不会,如果两堆牛都被所有人认为很厉害,那么这两堆牛两两之间一定都觉得自己很厉害,其实还是一堆牛。
              那么,这就可以演化为一个图,有n个点,m条有向边,求唯一的一个出度为0的强联通分量中元素的个数。
              为什么唯一呢?
              显然,如果有两个出度为0的强连通分量,那么这两个强连通分量都不会觉得对方分量的牛很厉害,而原题是找被所有牛都觉得很厉害,于是此时没有牛被所有牛认为很厉害。
             我们用链表存储点的关系,用tarjian找强连通分量,最后用强连通分量的出度判断是否是我们找的那一群牛,统计牛的个数就可以了。
上代码:

#include<stdio.h>
#include<string.h>
struct list
{
int v;
list *next;
};
list *head[10010],*rear[10010];
int dfn[10010],low[10010],stack[10010],s[10010],top,times,cnt;
bool instack[10010],chu[10010];
void tarjian(int v)
{
dfn[v]=low[v]=++times;
instack[v]=true;
stack[top++]=v;
for(list *p=head[v];p!=NULL;p=p->next)
if(!dfn[p->v])
{
tarjian(p->v);
if(low[p->v]<low[v]) low[v]=low[p->v];
}else if(instack[p->v]&&low[p->v]<low[v]) low[v]=low[p->v];
if(low[v]==dfn[v])
{
++cnt;
do
{
v=stack[--top];
instack[v]=false;
s[v]=cnt;
}while(low[v]!=dfn[v]);
}
return;
}
int main()
{
int n,m,i,begin,to,a,b;
scanf("%d%d",&n,&m);
memset(rear,0,sizeof(rear));
memset(head,0,sizeof(head));
for(i=0;i<m;++i)
{
scanf("%d%d",&begin,&to);
if(rear[begin]!=NULL)
{
rear[begin]->next=new list;
rear[begin]=rear[begin]->next;
}else head[begin]=rear[begin]=new list;
rear[begin]->next=NULL;
rear[begin]->v=to;
}
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(stack,0,sizeof(stack));
memset(s,0,sizeof(s));
times=cnt=top=0;
for(i=1;i<=n;++i) if(!dfn[i]) tarjian(i);
if(cnt==1)
{
printf("%d\n",n);
return 0;
}
memset(chu,false,sizeof(chu));
for(i=1;i<=n;++i)
for(list *p=head[i];p!=NULL;p=p->next)
if(s[i]!=s[p->v])
chu[s[i]]=true;
a=0;
for(i=1;i<=cnt;++i) if(chu[i]) ++a;else b=i;
if(a==cnt-1)
{
a=0;
for(i=1;i<=n;++i) if(s[i]==b) ++a;
printf("%d\n",a);
}else printf("0\n");
return 0;
}

  

   

[强连通分量] POJ 2186 Popular Cows的更多相关文章

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

    poj 2186 Popular Cows 题意: 有N头牛, 给出M对关系, 如(1,2)代表1欢迎2, 关系是单向的且能够传递, 即1欢迎2不代表2欢迎1, 可是假设2也欢迎3那么1也欢迎3. 求 ...

  2. poj 2186 Popular Cows (强连通分量+缩点)

    http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissi ...

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

    题目地址:http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Sub ...

  4. POJ 2186 Popular Cows (强联通)

    id=2186">http://poj.org/problem? id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 655 ...

  5. tarjan缩点练习 洛谷P3387 【模板】缩点+poj 2186 Popular Cows

    缩点练习 洛谷 P3387 [模板]缩点 缩点 解题思路: 都说是模板了...先缩点把有环图转换成DAG 然后拓扑排序即可 #include <bits/stdc++.h> using n ...

  6. POJ 2186 Popular Cows(强连通分量Kosaraju)

    http://poj.org/problem?id=2186 题意: 一个有向图,求出点的个数(任意点可达). 思路: Kosaraju算法的第一次dfs是后序遍历,而第二次遍历时遍历它的反向图,从标 ...

  7. POJ 2186 Popular Cows(强连通分量)

    [题目链接] http://poj.org/problem?id=2186 [题目大意] 给出一张有向图,问能被所有点到达的点的数量 [题解] 我们发现能成为答案的,只有拓扑序最后的SCC中的所有点, ...

  8. POJ 2186 Popular Cows --强连通分量

    题意:给定一个有向图,问有多少个点由任意顶点出发都能达到. 分析:首先,在一个有向无环图中,能被所有点达到点,出度一定是0. 先求出所有的强连通分支,然后把每个强连通分支收缩成一个点,重新建图,这样, ...

  9. poj 2186 "Popular Cows"(强连通分量入门题)

    传送门 参考资料: [1]:挑战程序设计竞赛 题意: 每头牛都想成为牛群中的红人. 给定N头牛的牛群和M个有序对(A, B),(A, B)表示牛A认为牛B是红人: 该关系具有传递性,所以如果牛A认为牛 ...

随机推荐

  1. 获取表单选中的值(利用php和js两种方式)

    php代码中获取表单中单选按钮的值: (单选按钮只能让我们选择一个,这里有一个“checked”属性,这是用来默认选取的,我们每次刷新我们的页面时就默认为这个值.) 例: <form name= ...

  2. RunTime的一些用法

    RunTime的一些用法   RunTime简介 RunTime简称运行时.OC就是运行时机制,其中最主要的是消息机制 对于OC来说,在编译的时候并不能决定真正调用哪个函数,只有真正运行时才会根据函数 ...

  3. 20160411002 经典SQL语句大全

    一.基础 1.说明:创建数据库CREATE DATABASE database-name 2.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备 ...

  4. 为linux系统添加虚拟内存swap分区

    阿铭linux学习笔记之swap分区 一.作用: swap分区是交换分区,在系统物理内存不足时与swap进行交换,对web服务器的性能影响极大,通过调整swap分区大小来提升服务器的性能,节省资源费用 ...

  5. 我的android学习经历35

    这几天又把android的基础知识全部复习了一遍,没有第一次那么难,感觉简单了好多,也发现了许多细节问题,发现了自己在网络编程方面的不足. 下面列举一些小的细节问题: 1.String,StringB ...

  6. Java中byte与16进制字符串的互相转换

    * Convert byte[] to hex string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串. * @param s ...

  7. 【转载】详解CreateProcess调用内核创建进程的过程

    原文:详解CreateProcess调用内核创建进程的过程 昨天同学接到了腾讯的电面,有一题问到了CreateProcess创建进程的具体实现过程,他答得不怎么好吧应该是, 为了以防万一,也为了深入学 ...

  8. WinForm关闭窗体彻底的退出方式

    //System.Environment.Exit(0); //Process.GetCurrentProcess().Kill(); //System.Threading.Thread.Curren ...

  9. CSS布局基础之二认识Viewport

    什么是viewport viewport,等同于浏览器窗口. 功能:约束你网站中最顶级包含块(containing block)元素html标签. 什么是包含块(containing block)?下 ...

  10. jquery总结05-常用事件03-键盘事件

    键盘事件 .keydown() 键盘按下触发,返回的的是键盘按键代码 .keyup() 键盘松手触发,返回的是键盘按键代码 .keypress() 键盘按下触发,返回的是敲击的字符的ASCII码