poj 2186 tarjian与gabow算法
来源:互联网 发布:yum ifconfig 编辑:程序博客网 时间:2024/06/05 03:02
Popular Cows
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 18198 Accepted: 7330
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.
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.
* 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 31 22 12 3
Sample Output
1
题意:问那个牛最受欢迎。即问有多少个点其他任何点都能到达。单向连通。
思路:强连通缩点。求出度为零的点(强连通分量),这个点只能有一个,输出这个强连通分量重点的个数,否则输出0。
tarjian算法与gabow算法,二者的思想是相同的,只是一个用数组存,一个是用的栈来维护的那个追溯到的父节点。据说:Galow算法更省时。
tarjian算法代码:
#include<iostream>#include<string.h>#include<stdio.h>#include<vector>using namespace std;#define max_n 10005#define max_e 250002#define inf 99999999int stack[max_n],top;//栈int isInStack[max_n];//是否在栈内int low[max_n],dfn[max_n],tim;//点的low,dfn值;time从1开始int node_id;//强连通分量的个数int head[max_n],s_edge;//邻接表头 s_edge从1开始int gro_id[max_n];//记录某个点属于哪个强连通分量int n,m;int in[max_n],out[max_n];//出度与入度vector<int> vec[max_n];//边的后节点存储struct Node{ int to; int next;} edge[max_e];void init()//初始化{ s_edge=0;//存储 memset(head,0,sizeof(head)); memset(edge,0,sizeof(edge)); top=0;//tarjian初始化 tim=0; node_id=0; memset(isInStack,0,sizeof(isInStack)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(in,0,sizeof(in));//出度入度的初始化 memset(out,0,sizeof(out));}void addedge(int u,int v){ s_edge++; edge[s_edge].to=v; edge[s_edge].next=head[u]; head[u]=s_edge;}int min(int a,int b){ if(a<b)return a; else return b;}void tarjan(int u){ //low值为u或u的子树能够追溯到得最早的栈中节点的次序号 stack[top++]=u; isInStack[u]=1; dfn[u]=++tim; //记录点u出现的记录,并放在栈中 low[u]=tim; int e,v; for(e=head[u]; e; e=edge[e].next) //如果是叶子节点,head[u]=0,edge[e].next=0; { v=edge[e].to; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(isInStack[v]) low[u]=min(low[u],dfn[v]); } int j; if(dfn[u]==low[u])//找到一个强连通,元素出栈 { node_id++; while(j=stack[--top]) { isInStack[j]=0; gro_id[j]=node_id; if(j==u)break; } }}void find()//tarjian寻找{ for(int i = 1 ; i <=n ; ++i) { if(!dfn[i]) { tarjan(i); } }}int main(){ int a,b; while(scanf("%d %d",&n,&m)!=EOF) { init(); for(int i=1; i<=n; i++) vec[i].clear(); for(int i = 0 ; i <m ; ++i) { scanf("%d%d",&a,&b); vec[a].push_back(b); addedge(a,b); } find(); int sum=0,sum1=0; for(int i=1; i<=n; i++) { for(int j=0; j<vec[i].size(); j++)//求强连通分量的出、入度 { if(gro_id[i]!=gro_id[vec[i][j]]) { out[gro_id[i]]++; //in[gro_id[vec[i][j]]]++; } } } int ans=0; for(int i=1; i<=node_id; i++) { if(out[i]==0) { sum++; for(int j=1;j<=n;j++) if(gro_id[j]==i) sum1++; } if(ans<sum1) ans=sum1; //if(in[i]==0) //sum1++; } if(sum==1) cout<<ans<<endl; else cout<<"0"<<endl; } return 0;}/*13 31 22 33 1*/
Gabow算法代码:
#include<iostream>#include<string.h>#include<stdio.h>#include<vector>using namespace std;#define max_n 10005#define max_e 250002#define inf 99999999int stack[max_n],stack1[max_n],top,top1;//栈int dfn[max_n],tim;//dfn值;time从1开始int node_id;//强连通分量的个数int gro_id[max_n];//记录某个点属于哪个强连通分量int n,m;int in[max_n],out[max_n];//出度与入度vector<int> vec[max_n];//边的后节点存储vector<int> cvec[max_n];//存储每个强连通分量的元素void init()//初始化{ top=0;//tarjian初始化 top1=0; tim=0; node_id=0; memset(dfn,-1,sizeof(dfn)); memset(in,0,sizeof(in));//出度入度的初始化 memset(out,0,sizeof(out)); memset(stack,-1,sizeof(stack)); memset(stack1,-1,sizeof(stack1)); memset(gro_id,-1,sizeof(gro_id));}void Gabow(int u){ stack[++top]=u; stack1[++top1]=u;//相当于low数组 dfn[u]=tim++; //记录点u出现的记录,并放在栈中 int e,v; for(e=0; e<vec[u].size(); e++) { v=vec[u][e]; if(dfn[v]==-1) { Gabow(v); } else if(gro_id[v]==-1) { while(dfn[stack1[top1]]>dfn[v]) top1--; } } int j; if(stack1[top1]==u)//找到一个强连通,元素出栈 { ++node_id; --top1; do { gro_id[stack[top]]=node_id; cvec[node_id].push_back(stack[top]); }while(stack[top--]!=u); }}void find(){ for(int i = 1 ; i <=n ; ++i) { if(dfn[i-1]==-1) { Gabow(i-1); } }}int main(){ int a,b; while(scanf("%d %d",&n,&m)!=EOF) { init(); for(int i=0; i<=n; i++) { vec[i].clear(); cvec[i].clear(); } for(int i = 0 ; i <m ; ++i) { scanf("%d%d",&a,&b); vec[a-1].push_back(b-1); } find(); int sum=0,sum1=0; for(int i=0; i<n; i++) { for(int j=0; j<vec[i].size(); j++)//求强连通分量的出、入度 { if(gro_id[i]!=gro_id[vec[i][j]]) { out[gro_id[i]]++; //in[gro_id[vec[i][j]]]++; } } } int ans=0; for(int i=1; i<=node_id; i++) { if(out[i]==0) { sum++; ans=cvec[i].size(); } } if(sum==1) cout<<ans<<endl; else cout<<"0"<<endl; } return 0;}/*3 31 22 12 3*/
- poj 2186 tarjian与gabow算法
- Gabow算法
- 链式前向星,kosaraju,Tarjan,Gabow算法的理解,POJ 2186 Popular Cows(强连通分量)
- Gabow算法【转自nocow】
- POJ 3417 Network(dp+tarjian LCA)
- tarjian算法 最大强连通分支
- poj1236 Network of Schools Tarjian算法
- 【笔记】tarjian算法 求强连通分量
- 强连通分支算法--Tarjan算法和Gabow算法
- [学习]用tarjian算法求强连通分量,tarjian算法缩点[学习知识~]
- 求强连通分量的tarjan算法Gabow算法
- poj 2553 tarjian+缩点。。。强连通分量
- poj 2553 tarjian+缩点。。。强连通分量
- 有向图强连通分量的Tarjian算法
- 6.3.1 强连通分支算法--Kosaraju算法、Tarjan算法和Gabow算法
- Tarjian【Template】
- 求强连通分量的三种算法——Kosaraju, Tarjan, Gabow
- POJ2186 Popular Cows 【裸缩环+Gabow算法强连通分量分解再建图】
- ORACLE中两个有可能都为NULL的字符串是否相等的比较
- 悼念512汶川大地震遇难同胞——来生一起走 hdu2189 动态规划
- ePub
- 把索引建在与表不同的表空间
- Magento目录页设置布局及添加新布局的方法
- poj 2186 tarjian与gabow算法
- C语言的指针类型解析
- C/C++内存存储的几个问题
- SlickEdit 使用技巧大收集
- HDU 2546 01背包,可达性问题 hash思想
- 使用PhoneGap开发简单案例
- linux 下源码安装python 2.6.8
- 我的Linux书架
- 如何支持新字体