题目描述:

有一些奶牛,其中某些奶牛受其他奶牛欢迎。每头奶牛都喜欢自己,同时都追随它喜欢奶牛的爱好。如果A喜欢B,而B喜欢C,那么A也会喜欢C。如果所有人都喜欢某头奶牛,那么这头奶牛就称之为绝对奶牛。

现在有N头奶牛,同时告诉你M条A喜欢B的信息,请你计算出有多少头绝对奶牛。

输入描述:

输入文件第一行是N和M。此后M行,每行两个整数A,B(1<=A,B<=N),表示奶牛B受奶牛A欢迎,也就是奶牛A喜欢奶牛B。

输出描述:

输出文件仅有一行,是绝对奶牛的数目。

输入样例:

3 3
1 2
2 1
2 3

输出样例:

1

数据范围:

对于30%的数据,有1<=N<=1000,1<=M<=5000;

对于100%的数据,有1<=N<=100000,1<=M<=500000。

-----------------------------------------------------------------

Tarjan求强连通分支

代码如下

#include <cstdio>
#include <algorithm>
struct Edge {int from, to;Edge* next;
};
const int MAXN = 100001, MAXM = 500001;
struct UFS {int father[MAXN], rank[MAXN], root(int);void initialize(int), plus(int, int);
};
int n, m, low[MAXN], dfn[MAXN], nowdfn, stk[MAXN], top, s[MAXN];
Edge* head[MAXN];
bool vis[MAXN], ins[MAXN];
Edge edges[MAXM];
UFS ufs;
void dfs(int);
int main() {int cnt = 0, tmp;scanf("%d%d", &n, &m);for(int i = 1; i <= m; i++) {int s, t;Edge* tmp = new Edge;scanf("%d%d", &s, &t);tmp->from = s;tmp->to = t;tmp->next = head[s];head[s] = tmp;}ufs.initialize(n);for(int i = 1; i <= n; i++) {if(!vis[i]) {dfs(i);}}for(int i = 1; i <= n; i++) {for(Edge* j = head[i]; j != NULL; j = j->next) {if(ufs.root(i) != ufs.root(j->to)) {s[ufs.root(i)]++;}}}for(int i = 1; i <= n; i++) {if(ufs.root(i) == i && s[i] == 0) {cnt++;tmp = i;}}printf("%d\n", cnt == 1 ? ufs.rank[tmp] : 0);return 0;
}
void UFS::initialize(int n) {for(int i = 1; i <= n; i++) {father[i] = i;rank[i] = 1;}
}
int UFS::root(int x) {return father[x] == x ? x : root(father[x]);
}
void UFS::plus(int x, int y) {father[y] = x;rank[x] += rank[y];
}
void dfs(int x) {nowdfn++;top++;dfn[x] = low[x] = nowdfn;ins[x] = vis[x] = true;stk[top] = x;for(Edge* i = head[x]; i != NULL; i = i->next) {int go = i->to;if(!vis[go]) {dfs(go);low[x] = std::min(low[x], low[go]);}if(ins[go]) {low[x] = std::min(low[x], dfn[go]);}}if(dfn[x] == low[x]) {int f = stk[top];top--;if(f != x) {while(true) {int i = stk[top];top--;ufs.plus(f, i);if(i == x) {break;}}}}
}

但是会爆递归栈只有70分

Egg Pain的我就Egg Pain地写了一个Egg Pain的递归栈模拟,特此纪念,看代码。!

#include <cstdio>
#include <algorithm>
struct Edge {int from, to;Edge* next;
};
const int MAXN = 100001, MAXM = 500001;
struct UFS {int father[MAXN], rank[MAXN], root(int);void initialize(int), plus(int, int);~UFS();
};
struct Cell {int x;bool finished, first, visjto;Edge* j;void call();
};
int n, m, low[MAXN], dfn[MAXN], nowdfn, stk[MAXN], top, s[MAXN], cst;
bool vis[MAXN], ins[MAXN];
Edge* head[MAXN];
UFS ufs;
Cell cs[MAXN];
int main() {int cnt = 0, tmp;freopen("popular.in", "r", stdin);freopen("popular.out", "w", stdout);scanf("%d%d", &n, &m);for(int i = 1; i <= m; i++) {int s, t;Edge* tmp = new Edge;scanf("%d%d", &s, &t);tmp->from = s;tmp->to = t;tmp->next = head[s];head[s] = tmp;}ufs.initialize(n);for(int i = 1; i <= n; i++) {if(!vis[i]) {cst = 1;cs[cst].x = i;cs[cst].first = true;cs[cst].finished = false;while(cst != 0) {cs[cst].call();if(cs[cst].finished) {cst--;}}}}for(int i = 1; i <= n; i++) {for(Edge* j = head[i]; j != NULL; j = j->next) {if(ufs.root(i) != ufs.root(j->to)) {s[ufs.root(i)]++;}}}for(int i = 1; i <= n; i++) {if(ufs.root(i) == i && s[i] == 0) {cnt++;tmp = i;}}printf("%d\n", cnt == 1 ? ufs.rank[tmp] : 0);for(int i = 1; i <= n; i++) {while(head[i] != NULL) {Edge* tmp = head[i]->next;delete head[i];head[i] = tmp;}}fclose(stdin);fclose(stdout);return 0;
}
void UFS::initialize(int n) {for(int i = 1; i <= n; i++) {father[i] = i;rank[i] = 1;}
}
int UFS::root(int x) {return father[x] == x ? x : root(father[x]);
}
void UFS::plus(int x, int y) {father[y] = x;rank[x] += rank[y];
}
UFS::~UFS() {delete[] father;delete[] rank;
}
void Cell::call() {if(first) {nowdfn++;top++;dfn[x] = low[x] = nowdfn;ins[x] = vis[x] = true;stk[top] = x;j = head[x];first = false;}else {if(!visjto) {low[x] = std::min(low[x], low[j->to]);}if(ins[j->to]) {low[x] = std::min(low[x], dfn[j->to]);}j = j->next;}if(j == NULL) {if(low[x] == dfn[x]) {int f = stk[top];top--;if(f != x) {while(true) {int i = stk[top];top--;ufs.plus(f, i);if(i == x) {break;}}}}finished = true;}else {if(!vis[j->to]) {cst++;cs[cst].x = j->to;cs[cst].first = true;cs[cst].finished = false;visjto = false;}else {visjto = true;}}
}

转载于:https://www.cnblogs.com/nealchen/p/4237526.html

《受欢迎的奶牛》和强连通分支Tarjan算法相关推荐

  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. tarjan算法不是很懂先mark一下。

     前面为转载的.后面是自己的理解. 三种tarjan算法(上) .这篇算是做一个总结吧. 求强连通分量 求无向图的割和桥 最近公共祖先 求强连通分量 基本概念:       强连通是有向图才有的概念. ...

  4. 算法提高课-图论-有向图的强连通分量-AcWing 367. 学校网络:强连通分量、tarjan算法

    文章目录 题目解答 题目来源 题目解答 来源:acwing 分析: 第一问:通过tarjan算法求出强连通分量并且缩点后,统计入度为0的点的个数p即可. 第二问,至少加几条边才能使图变成强连通分量?这 ...

  5. CSP认证201509-4 高速公路[C++题解]:强连通分量、tarjan算法模板题

    题目分析 来源:acwing 分析: 所求即为强连通分量的个数,然后计算每个强连通分量中点的个数,相加即可. 所谓强连通分量,它是一个子图,其中任意两点可以相互到达,并且再加一个点,就不能满足任意两点 ...

  6. 有向图强连通分量tarjan算法

    转自:http://www.byvoid.com/blog/scc-tarjan/ http://blog.csdn.net/geniusluzh/article/details/6601514 在有 ...

  7. Popular Cows POJ - 2186(tarjan算法)+详解

    题意: 每一头牛的愿望就是变成一头最受欢迎的牛.现在有 N头牛,给你M对整数(A,B),表示牛 A认为牛B受欢迎.这种关系是具有传递性的,如果 A认为 B受欢迎, B认为 C受欢迎,那么牛 A也认为牛 ...

  8. tarjan算法求解强连通分量问题

    Part1:有向图的强连通分量: 一个连通图只有一个联通分量就是自身,非连通图有多个连通分量. 在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从v ...

  9. Tarjan算法小结1——SCC

    引入 许多最短单源路径算法,如Dijkstra,SPFA, floyd, Bellman-Ford等,在运用时只能给出指定点到任意点的最短距离,抑或是给出图中是否有环的信息,并不能准确确定环的个数.包 ...

  10. Tarjan算法流程和简要证明

    声明: 一下许多内容摘自: 北京大学暑期课<ACM/ICPC竞赛训练>强连通分支.桥和割点 北京大学信息学院 郭炜 不建议初学者直接看这篇博文 可以先了解一下Tarjan算法的具体流程,再 ...

最新文章

  1. sharepoint性能优化
  2. CF570D Tree Requests
  3. python3 文件 复制、重命名、移动、删除
  4. windows在命令行中查看当前路径
  5. Linux 进程管理剖析--转
  6. 未来教育计算机二级为什么分数很低,计算机二级考试失分了却不知道为什么?...
  7. 截取中文字符长度(中文、字母都有效)
  8. python字符串加减乘除_python 数字字符串加减乘除-女性时尚流行美容健康娱乐mv-ida网...
  9. java载屁股针_以前常打的“屁股针”,为何现在很少见了?医生告诉你真实原因...
  10. echart 地图 某个地区_一站式解决echarts实现区域地图
  11. python数据可视化的包怎么安装_数据可视化包 - matplotlib
  12. 程序员究竟还需要读书么?
  13. php+模版取余,PHP取余函数介绍MOD(x,y)与x%y_php技巧
  14. Codejock Toolkit工具包专业版
  15. Word文档批量导入
  16. 计算机网络中属于通信子网,计算机网络通常被划分为通信子网和资源子网,通信子网提供信息传输服务,资源子网提供共享资源。...
  17. 离散数学西电版复习笔记——第一章:命题逻辑
  18. socket closed解决办法
  19. 什么叫同步,什么叫异步?
  20. 向图档插入外部DWG图片 auto CAD .NET二次开发

热门文章

  1. SVN仓库解决APIcloud2检出错误
  2. Outlook验证服务器证书,OUTLOOK2019 解决 无法验证您连接到的服务器使用的安全证书...
  3. php必填参数校验,laravel请求参数校验方法
  4. oracle+11g+32位数据库能导入到64位么,Oracle 11G数据库导出问题解决
  5. 百度区块链 xuperchain 节点端 tps统计脚本
  6. matlab重叠图像块拼接,在matlab中拼接图像时如何正确混合?
  7. java泛型特点_Java泛型
  8. GSON简单实用及常用方法(附 .jar 地址)
  9. JDBC学习(四、DAO思想和重构设计上)
  10. Mac 系统下 配置多个ssh-key (git sourcetree)