POJ2168结题报告【强连通分量】
来源:互联网 发布:mac桌面文件复制到u盘 编辑:程序博客网 时间:2024/05/20 18:42
Popular Cows
Time Limit: 2000MS Memory Limit: 65536KTotal Submissions: 16924 Accepted: 6796
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
Hint
Cow 3 is the only cow of high popularity.
Source
USACO 2003 Fall
题目大意:牛之间有一个崇拜关系,如A崇拜B。崇拜关系是可以继承的,如果A崇拜B,B崇拜C,那么A同时也会崇拜C(所谓爱屋及乌吧0 0)。现在让你求被所有牛崇拜的牛共有几头。
解题思路:求强连通分量。强连通分量的定义是,处于强连通分量中的任意两个点之间都存在路径。所以如果把崇拜关系抽象成图中的有向边,牛抽象成点,那么处于一个强连通分量中的牛就有这样的关系:他们之间任意两牛之间都有路径,也就是互相崇拜。这样先求出图中的强连通分量,把这些牛分成若干“群”牛,处于同一群牛中的牛是互相崇拜的,而且如果某一群中的某头牛D崇拜另一群中的某头牛,那么这头牛所处的牛群中的每头牛都会崇拜D所崇拜的那头牛所在的牛群中的每头牛。把每个牛群都看成一个图中的点,所以只要找到入度为0的牛群即可,如果只存在一个入读为0的牛群那么答案就是这个牛群的牛的个数,如果存在2个或2个以上的入读为0的牛群,那么答案就是0了(因为这些牛群相互不崇拜)。
(因为刚刚学习强连通分量,三个算法都试着是实现了下)
代码:kosaraju
#include<cstdio>#include<cstring>#include<queue>#include<stack>using namespace std;#define INF 0x7ffffff#define MAX_NODE 10010#define MAX_SIDE 500010int node[MAX_NODE];int rnode[MAX_NODE];struct SIDE{ int to,next; SIDE(int to,int next):to(to),next(next){} SIDE(){}}side[2*MAX_SIDE];int top;void add_side(int u,int v){ side[top]=SIDE(v,node[u]); node[u]=top++; side[top]=SIDE(u,rnode[v]); rnode[v]=top++;}bool visit[MAX_NODE];int time[MAX_NODE];int witch[MAX_NODE];int num[MAX_NODE];int n,m;int q[MAX_NODE];int mark;int current;int rdfs(int u){ //printf("rdfs %d\n",u); visit[u]=true; for(int i=rnode[u];i!=-1;i=side[i].next){ int v=side[i].to; if(!visit[v]){ rdfs(v); } } q[mark++]=u;}int dfs(int u){ //printf("dfs %d\n",u); visit[u]=true; witch[u]=current; num[current]++; for(int i=node[u];i!=-1;i=side[i].next){ int v=side[i].to; if(!visit[v]){ dfs(v); } }}int kosaraju(){ memset(visit,0,sizeof(visit)); mark=1; for(int i=1;i<=n;i++){ if(!visit[i]){ rdfs(i); } } memset(visit,0,sizeof(visit)); memset(num,0,sizeof(num)); current=0; for(int i=n;i;i--){ int u=q[i]; if(!visit[u]){ dfs(u); current++; } } //printf("current %d\n",current);}bool out[MAX_NODE];int solve(){ memset(out,0,sizeof(out)); for(int u=1;u<=n;u++){ if(out[witch[u]])continue; for(int i=node[u];i!=-1;i=side[i].next){ int v=side[i].to; if(witch[v]!=witch[u]){ out[witch[u]]=true; break; } } } int r=0; for(int i=0;i<current;i++){ if(!out[i]){ if(r)return 0; r=num[i]; } } return r;}int main(){ scanf("%d%d",&n,&m); memset(node,-1,sizeof(node)); memset(rnode,-1,sizeof(rnode)); top=0; for(int i=0;i<m;i++){ int from,to; scanf("%d%d",&from,&to); add_side(from,to); } kosaraju(); printf("%d\n",solve()); return 0;}
代码:tarjan
#include<cstdio>#include<cstring>#include<stack>using namespace std;#define INF 0x7ffffff#define MAX_NODE 10100#define MAX_SIDE 50100int node[MAX_NODE];struct SIDE{ int to,next; SIDE(int to,int next):to(to),next(next){} SIDE(){}}side[MAX_SIDE];int top;void add_side(int u,int v){ side[top]=SIDE(v,node[u]); node[u]=top++;}int num[MAX_NODE];int low[MAX_NODE];int dfn[MAX_NODE];stack<int>q;int time;int sum;void dfs(int u){ int v; low[u]=dfn[u]=time++; q.push(u); for(int i=node[u];i!=-1;i=side[i].next){ v=side[i].to; if(!dfn[v]){ dfs(v); } if(dfn[v]!=-1){ low[u]=min(low[u],low[v]); } } if(low[u]==dfn[u]){ do{ v=q.top(); q.pop(); dfn[v]=-1; num[sum]++; low[v]=sum; }while(v!=u); sum++; }}int n,m;void tarjan(){ sum=0,time=1; memset(num,0,sizeof(num)); memset(dfn,0,sizeof(dfn)); while(!q.empty())q.pop(); for(int i=1;i<=n;i++){ if(!dfn[i])dfs(i); }}bool out[MAX_NODE];int solve(){ memset(out,0,sizeof(out)); for(int u=1;u<=n;u++){ if(out[low[u]])continue; for(int i=node[u];i!=-1;i=side[i].next){ int v=side[i].to; if(low[v]!=low[u]){ out[low[u]]=true; break; } } } int r=0; for(int i=0;i<sum;i++){ if(!out[i]){ if(r)return 0; r=num[i]; } } return r;}int main(){ scanf("%d%d",&n,&m); memset(node,-1,sizeof(node)); top=0; for(int i=0;i<m;i++){ int from,to; scanf("%d%d",&from,&to); add_side(from,to); } tarjan(); printf("%d\n",solve()); return 0;}
代码:gabow
#include<cstdio>#include<cstring>#include<stack>using namespace std;#define MAX_NODE 10100#define MAX_SIDE 50100int node[MAX_NODE];struct SIDE{ int to,next; SIDE(int to,int next):to(to),next(next){} SIDE(){}}side[MAX_SIDE];int top;void add_side(int u,int v){ side[top]=SIDE(v,node[u]); node[u]=top++;}stack<int>q;stack<int>temp;int dfn[MAX_NODE];int num[MAX_NODE];int belong[MAX_NODE];int time;int sum;int m,n;void dfs(int u){ int v; dfn[u]=time++; q.push(u);temp.push(u); for(int i=node[u];i!=-1;i=side[i].next){ v=side[i].to; if(!dfn[v])dfs(v); else if(!belong[v]){ while(dfn[temp.top()]>dfn[v])temp.pop(); } } if(u==temp.top()){ sum++; temp.pop(); do{ v=q.top();q.pop(); num[sum]++; belong[v]=sum; }while(v!=u); }}void gabow(){ sum=0;time=1; while(!q.empty())q.pop(); while(!temp.empty())temp.pop(); memset(num,0,sizeof(num)); memset(belong,0,sizeof(belong)); memset(dfn,0,sizeof(dfn)); for(int i=1;i<=n;i++){ if(!dfn[i])dfs(i); }}bool out[MAX_NODE];int solve(){ memset(out,0,sizeof(out)); int v; for(int u=1;u<=n;u++){ if(out[belong[u]])continue; for(int i=node[u];i!=-1;i=side[i].next){ v=side[i].to; if(belong[u]!=belong[v]){ out[belong[u]]=true; break; } } } int r=0; for(int i=1;i<=sum;i++){ if(!out[i]){ if(r)return 0; r=num[i]; } } return r;}int main(){ top=0; memset(node,-1,sizeof(node)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int from,to; scanf("%d%d",&from,&to); add_side(from,to); } gabow(); printf("%d\n",solve()); return 0;}
- POJ2168结题报告【强连通分量】
- 强连通分量基础题
- NOIP2015 信息传递 解题报告(强连通分量)
- HDU 1827&&3072 强连通分量 解题报告
- 【训练题】强连通分量缩点
- 收缩强连通分量
- 强连通分量
- POJ2181强连通分量
- 强连通分量模板
- POJ_2762_强连通分量
- 强连通分量
- 强连通分量
- 强连通分量
- 强连通分量
- 【强连通分量】传话
- 强连通分量 关节点
- poj2186强连通分量
- 强连通分量
- 网页爬虫抓取URL简单实现
- c++ string中的replace
- 记ORA-01031: insufficient privileges一则
- svn解决冲突
- 第五节:C64+ DSP 部分术语翻译
- POJ2168结题报告【强连通分量】
- 多线程开启gprof性能测试的简易方法
- 【应用开发】网络编程
- eclipse 常用快捷键
- 进程管理(二)
- java 程序打开网页
- Linux下VsFTP配置全方案
- 久违的CSDN
- Ubuntu-10.04-AMD64常见问题