【例题】
每头牛都有一个梦想:成为一个群体中最受欢迎的名牛!在一个有N(1<=N<=10,000)头牛的牛群中,给你M(1<=M<=50,000)个二元组(A,B),表示A认为B是受欢迎的。既然受欢迎是可传递的,那么如果A认为B受欢迎,B又认为C受欢迎,则A也会认为C是受欢迎的,哪怕这不是十分明确的规定。你的任务是计算被所有其它的牛都喜欢的牛的个数。
Input Format
第一行,两个数,N和M。第2~M+1行,每行两个数,A和B,表示A认为B是受欢迎的。
Output Format
一个数,被其他所有奶牛认为受欢迎的奶牛头数。


1.利用强连通分量缩点

在知道强连通分量之后,我们可以对图的连通性有一个新的认识:在每个连通分量构成的点集合中,每两个点之间都是互相联通的。那么在解关于连通性的问题的时候,可以把这一整个集合当做一个点,即“缩点”。
在例题里,我们要求被其他所有奶牛认为受欢迎的奶牛头数,转换到图算法,即求和其他任意一个顶点都是连通的点的个数(注意是有向图)。又因为在一个连通分量的集合里,任意两个点可以互相到达,所以我们就可以把这个集合作为顶点,把上万的数据量缩减到很小。

2.判断与搜索的方法

求解连通分量以后,面临的下一个问题是,对于所有的连通分量集合,哪一个集合是和其他所有集合连通的(集合里的奶牛不仅要两两互相认为是受欢迎的,其他集合里面的奶牛也要认为他们是受欢迎的)。
结论:

当且仅当只有一个集合,集合中的点的出度和为0(没有出边),这个集合中所有的元素才是满足要求的。(前提是没有被孤立的集合,也就是没有出度入度和为0的集合)

下面是证明:

我们假设四个集合分别都是互相连通的。
我们假设图中仅有黑色的实线边,那么图中就存在三个出度为0的集合,由图可知,没有满足的集合。
那么如果没有出度为0的集合呢?我们只考虑图中(1,3)(3,2)(2,4)(4,1)的边,那么很显然,四个集合其实就是连通的,那么在最初求连通分量的时候他们就会被和为一个集合,即:这种情况是不存在的。
对于任意n个点,要将他们单向连通,最少需要n-1条边(每条边为(u,u+1))。在这种情况下,有一个入度为0,有一个出度为0.那么出度为0的点,必定是其他任意点可以到达的。那么,在这里,只需要其他点都有一条出边,留下一个点的出度为0,那么这个点就是满足要求的。因为这样保证了至少有n-1条边,并且不会有两条边的两个顶点完全相同(否则会连通,如图中(2,3)和(3,2)),那么根据抽屉原理,这些边涉及的集合包括了所有的集合。那么就是一个单向连通的图。由上面的陈述可以知道,出度为0的点可以被任意一个顶点到达。
证明结束。
当然这不是特别严谨的证明,但我不知道严谨的证明在哪,这只是我的个人理解。


那么这道题就很简单了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;int N, M;
#define maxx 11000
struct Edges{int x, y, next;
}E[maxx * 5];   int ans = 0;
int V[maxx];
//
int low[maxx], dfn[maxx], ind = 0;//DFS
int stack[maxx], tails = 0;
bool Jud[maxx];
int SCC[maxx], sum = 0;
//
int OutDegree[maxx];
int printout = 0;void Putin()
{memset(V, -1, sizeof(V));memset(Jud, false, sizeof(Jud));memset(OutDegree, 0, sizeof(OutDegree));//cin >> N >> M;for(int i = 1; i <= M; i++){int xi;    int yi;cin >> xi >> yi;E[++ans].next = V[xi];E[ans].x = xi;    E[ans].y = yi;V[xi] = ans;}
}inline void DFS_tatjan(int x)
{dfn[x] = low[x] = ++ind;stack[++tails] = x;Jud[x] = true;for(int i = V[x]; i > 0; i = E[i].next){int y = E[i].y;if(!dfn[y]){DFS_tatjan(y);low[x] = min(low[x], low[y]);}else    low[x] = min(low[x], dfn[y]);}if(low[x] >= dfn[x]){int k; sum++;do{k = stack[tails--];Jud[k] = false;SCC[k] = sum;} while (k != x);}
}void Search()
{for(int i = 1; i <= M; i++){int a = SCC[E[i].x], b = SCC[E[i].y];if(a != b)  OutDegree[a]++;}int num = 0;//出度为0的点集的个数;int recall;//记录出度为0的点集的序号;for(int i = 1; i <= sum; i++){if(OutDegree[i] == 0)   num++, recall = i;if(num > 1)    break;}if(num == 1)for(int i = 1; i <= N; i++)if(SCC[i] == recall)    printout++;return;
}int main()
{Putin();for(int i = 1; i <= N; i++)if(!dfn[i])    DFS_tatjan(i);Search();cout << printout << endl;return 0;
}

【算法】【题解】【usaco】 最受欢迎的牛相关推荐

  1. 算法提高课-图论-有向图的强连通分量-AcWing 1174. 受欢迎的牛:tarjan算法求强连通分量、tarjan算法板子、强连通图

    文章目录 题目解答 题目来源 题目解答 来源:acwing 分析: 强连通图:给定一张有向图.若对于图中任意两个结点x,y,既存在从x到y的路径,也存在从y到x的路径,则称该有向图是"强连通 ...

  2. Tarjan算法详解(AcWing 1174 受欢迎的牛)

    题目描述: 每一头牛的愿望就是变成一头最受欢迎的牛. 现在有 N 头牛,编号从 1 到 N,给你 M 对整数 (A,B),表示牛 A 认为牛 B 受欢迎. 这种关系是具有传递性的,如果 A 认为 B ...

  3. 解题报告:luogu P2341 受欢迎的牛(Tarjan算法,强连通分量判定,缩点,模板)

    题目链接:洛谷 受欢迎的牛 基本上算是一道模板题 根据题意,如果有环,意味着这个环里的牛都互相喜欢 我们可以先求出环,然后把每一个环都看作一个点,这样整个图就变成了一个DAG(有向无环图) 看有几个点 ...

  4. 写了三百篇算法题解,关于如何刷题有些话我想对你说

    这篇文章憋了我挺久的,感觉都快憋出内伤,一次次的打开 Typora 写几十个字,一次次的修改删除最后关闭 Typora,如此反复. 为什么会如此纠结? 或许是太狂妄了,我真的想让那些看了这篇文章的人都 ...

  5. 洛谷P2341 [HAOI2006]受欢迎的牛 (Tarjan,SCC缩点)

    P2341 [HAOI2006]受欢迎的牛|[模板]强连通分量 https://www.luogu.org/problem/P2341 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就 ...

  6. 算法题解——将字符串转化为ip地址

    算法题解--将字符串转化为ip地址 题目描述 现在有一个只包含数字的字符串,将该字符串转化成IP地址的形式,返回所有可能的情况. 例如: 给出的字符串为"25525511135", ...

  7. BZOJ 1051: [HAOI2006]受欢迎的牛【Trajan】

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MB Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛 ...

  8. 洛谷——P2341 [HAOI2006]受欢迎的牛//POJ2186:Popular Cows

    P2341 [HAOI2006]受欢迎的牛/POJ2186:Popular Cows 题目背景 本题测试数据已修复. 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所 ...

  9. BZOJ 1051 受欢迎的牛(Tarjan缩点)

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4573  Solved: 2428 [Submit][S ...

  10. BZOJ 1051: [HAOI2006]受欢迎的牛

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 7120  Solved: 3779 [Submit][S ...

最新文章

  1. 对Tensor进行变换 class torchvision.transforms.Normalize(mean, std) 给定均值:(R,G,B) 方差:(R,G,B),将会把Tensor正则化
  2. 如何从0到1搭建电商促销系统?
  3. 征战蓝桥 —— 2013年第四届 —— C/C++A组第10题——大臣的旅费
  4. Autowire异常
  5. 使用Docker安装的Tuleap-aio.查看admin默认密码
  6. 泰山站和泰安站怎么区分?
  7. vb.net 同时给多个属性赋值_一个float值赋值给double,结果是什么?进来重温一下类型提升吧...
  8. 用Linux编写C语言程序
  9. 2011全年腾讯移动安全实验室手机病毒行业报告
  10. Oracle12C 基本操作和使用
  11. java编程小bug
  12. 程序员代码面试指南刷题--第四章.打气球的最大分数
  13. 学习信号量 sem_init、sem_destroy、sem_post、sem_wait、sem_trywait、sem_getvalue
  14. 【ceph】ceph-mds journal模块解读
  15. alert promt confirm js 用法
  16. Mac自带FTP工具用法
  17. qt_cannot find -lxxx, 链接动态/静态库失败
  18. 初中高中生用计算机,中学生如何科学的使用计算器?
  19. 电子秤称重系统设计,HX711压力传感器,51单片机(Proteus仿真、C程序、原理图、论文等全套资料)
  20. 【转自牛客网】C++类职位校招

热门文章

  1. [CLI] mp4box 分割合併mp4
  2. 第 7 章 文件和数据格式化
  3. 计算机保研记:北京交通大学
  4. C语言中文网-CPPSTL
  5. 临床路径在中国的实施现状及路径产品发展前景
  6. DirectIO(O_DIRECT) 详解
  7. 第2件事 培养独立思考能力,对“产品低智商”说不
  8. 思科中小型教育骨干网络解决方案
  9. [LeetCode]-Python刷题第三周(栈和队列)
  10. python 爬取电影天堂电影