POJ 2186:Popular Cows(tarjan算法入门题)
来源:互联网 发布:淘宝卖自己做的食品 编辑:程序博客网 时间:2024/05/29 07:37
题目链接:http://poj.org/problem?id=2186
题目意思:每一个牛的愿望是称为牛圈中最受欢迎的牛,在一个牛圈中共有N头牛,给出M对关系(A,B),
意思是牛A认为牛B很受欢迎,而且这种想法是会传递的,如果A认为B很受欢迎,B认为C很受欢迎,那么
A就会认为C是受欢迎的。你的任务是计算有多少牛让其他所有牛都认为它是最受欢迎的。
题目是一个强连通算法的入门题目。根据题目描述,我们就可以知道应该给出的一个关系网是有环存在的,
不然也不必问多少只牛让其他所有牛认为它是受欢迎的。
比如下面一组数据:自己随便写的一个数据
8 9
1 2
2 3
3 4
4 5
5 3
5 6
6 7
7 8
8 6
画出来就是这个图,然后可以看出对于6,7,8这三个牛来说,除自身外的所有牛都觉得自己
受欢迎,因此最后答案就是3.
解题思路:首先是进行缩点,给各个连通分量给出一个编号,我们把一个连通分量中的点同意看
成一个点,并用这个编号表示,对此对于缩点后的图来说,必须只能有一个出度为0的点,如果
多余一个的话,不能存在一些牛使其他所有牛都认为自己受欢迎。则答案就是0,否则我们就把
出度为0的点所在的连通分量的点做一个统计,统计到的点的个数就是答案。
POJ这个题目数据弱了,好多人说算法写得不对也可AC,不过我觉得自己写的是没问题的,测试了
讨论区的数据,差不多也都过了,感觉自己写的应该是正确的算法。
#include <iostream>#include <stdio.h>#include <string.h>using namespace std;const int maxm = 600000;const int maxn = 200000;int head[maxn]; ///链表头节点int Stack[maxn]; ///栈bool inStack[maxn]; ///用来标记节点是否在栈中int belong[maxn]; ///各个顶点所属于的连通分量int dfn[maxn]; ///时间标记int low[maxn]; ///相当于并查集int outdegree[maxn]; ///统计顶点入度int edgeNumber,time,top,cnt; ///time时间标记,top栈顶指针,cnt当前连通分量编号struct Edge{ int A; int B; int nex;}edge[maxm];void addEdge(int a,int b){ edge[edgeNumber].A = a; edge[edgeNumber].B = b; edge[edgeNumber].nex = head[a]; head[a] = edgeNumber++;}///强连通找各个连通分量所属的集合void tarjan(int a){ dfn[a] = low[a] = ++time; Stack[++top] = a; inStack[a] = true; for(int i = head[a]; i != -1; i = edge[i].nex) { int b = edge[i].B; if(!dfn[b]) ///没有被访问过 { tarjan(b); low[a] = min(low[a],low[b]); } else if(inStack[b]) { low[a] = min(low[a],dfn[b]); } } if(dfn[a] == low[a]) { cnt++; int temp; do { temp = Stack[top--]; inStack[temp] = false; belong[temp] = cnt; ///当前顶点属于第cnt个连通分量 }while(temp != a); }}void solve(int n,int m){ int a,b; edgeNumber = 0; memset(head,-1,sizeof(head)); for(int i = 1; i <= m; i++) { scanf("%d%d",&a,&b); addEdge(a,b); } top = time = cnt = 0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(outdegree,0,sizeof(outdegree)); for(int i = 1; i <= n; i++) inStack[i] = false; for(int i = 1; i <= n; i++) { if(dfn[i]==0) tarjan(i); } for(int i = 0; i < edgeNumber; i++) { a = edge[i].A; b = edge[i].B; a = belong[a]; b = belong[b]; if(a != b) ///不属于一个连通分量的话,我们统计出度 outdegree[a]++; } int num = 0; int temp; for(int i = 1; i <= cnt; i++) { if(outdegree[i]==0) { temp = i; num++; } } int ans = 0; if(num == 1) ///出度为1的点必须有且只能有一个 { for(int i = 1; i <= n; i++) { if(belong[i] == temp) ans++; } } printf("%d\n",ans);}int main(){ int N,M; while(~scanf("%d%d",&N,&M)) ///N头牛,M个关系 { solve(N,M); } return 0;}
阅读全文
0 0
- POJ 2186:Popular Cows(tarjan算法入门题)
- POJ 2186 Popular Cows Tarjan算法
- poj-2186-Popular Cows (tarjan算法)
- POJ 2186 Popular Cows(强连通分量Tarjan算法)
- POJ 2186:Popular Cows Tarjan模板题
- poj 2186 Popular Cows(Tarjan)
- POJ - 2186 - Popular Cows (tarjan)
- poj 2186 Popular Cows(Tarjan)
- POJ 2186Popular Cows(Tarjan)
- poj 2186 Popular cows ( tarjan )
- poj 2186 Popular Cows tarjan
- Popular Cows - POJ 2186 Tarjan
- Popular Cows poj 2186 tarjan
- POJ 2186 Popular Cows(Tarjan算法求强连通分量)
- POJ 2186 Popular Cows(强连通分量缩点,Tarjan算法)
- (tarjan缩点)poj 2186 Popular Cows
- poj 2186 Popular Cows (tarjan缩点)
- POJ 2186 Popular Cows (Tarjan + 缩点)
- java获得指定时间的时间戳
- RecyclerView多条目加载
- RMRC2016: B Election 组合数学
- Javascript中Math对象
- 盒子3D模型
- POJ 2186:Popular Cows(tarjan算法入门题)
- 文字颜色随机变换
- 使用EF从数据库表直接创建类
- 计算机网络:TCP与UDP(一)
- tomcat源码中Digester解析
- 洛谷 P1081开车旅行
- Hdu:2020 绝对值排序
- Apache的php版本配置
- 仿函数