POJ 2186 Popular Cows(强连通分量缩点)
2018-01-13 20:55
381 查看
Popular Cows
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.
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.
Output
* Line 1: A single integer that is the number of cows who are considered popular by every other cow.
Sample Input
Sample Output
Hint
Cow 3 is the only cow of high popularity.
Source
USACO 2003 Fall
思路:最直接的想法是暴力搜索,首先,如果一个点能够到达所有点,则这头牛崇拜所有的牛,那么反过来(将所有路线反向,即崇拜变为被崇拜)之后,如果某个点能到达所有点,那个这头牛就被所有的牛崇拜(逆向思维),不过这样做的复杂度高达O(m*n),会超时。只得另辟蹊径了,首先来看有向无环图,其中有两类点非常特殊,一种是入度为0的点,一种是出度为0的点,如果某个有向无环图中只有一个出度为0点,那么所有的点都有路径到达这个点,而且有且仅有这个点(DAG(有向无环图的性质
无论图是否连通 可以自己画一下))。如果题目中这个图是有向无环图就好办了,可惜不是。。。那么是不是可以转化成有向无环图呢,关键在于如何去掉环路,每个最大的环路其实就是一个连通分量,在这个环里面所有奶牛都是互相崇拜的,不用管环内部的情况,把每个环看成一个点,重新构图,再寻找出度为0的点,,出度为0的个数一定大于等于1(当原图为连通图时,转化为1个点,个数最小为1),如果等于1,答案则是出度为0对应的连通分量的点的个数。(注意如果图中有孤立的点也会被考虑进去,即出度为0的个数大于1)。这里求强连通分量用的是tarjan算法。
代码:
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 36225 | Accepted: 14759 |
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.
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.
Output
* Line 1: A single integer that is the number of cows who are considered popular by every other cow.
Sample Input
3 3 1 2 2 1 2 3
Sample Output
1
Hint
Cow 3 is the only cow of high popularity.
Source
USACO 2003 Fall
思路:最直接的想法是暴力搜索,首先,如果一个点能够到达所有点,则这头牛崇拜所有的牛,那么反过来(将所有路线反向,即崇拜变为被崇拜)之后,如果某个点能到达所有点,那个这头牛就被所有的牛崇拜(逆向思维),不过这样做的复杂度高达O(m*n),会超时。只得另辟蹊径了,首先来看有向无环图,其中有两类点非常特殊,一种是入度为0的点,一种是出度为0的点,如果某个有向无环图中只有一个出度为0点,那么所有的点都有路径到达这个点,而且有且仅有这个点(DAG(有向无环图的性质
无论图是否连通 可以自己画一下))。如果题目中这个图是有向无环图就好办了,可惜不是。。。那么是不是可以转化成有向无环图呢,关键在于如何去掉环路,每个最大的环路其实就是一个连通分量,在这个环里面所有奶牛都是互相崇拜的,不用管环内部的情况,把每个环看成一个点,重新构图,再寻找出度为0的点,,出度为0的个数一定大于等于1(当原图为连通图时,转化为1个点,个数最小为1),如果等于1,答案则是出度为0对应的连通分量的点的个数。(注意如果图中有孤立的点也会被考虑进去,即出度为0的个数大于1)。这里求强连通分量用的是tarjan算法。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<stdlib.h> #include<vector> #include<stack> using namespace std; #define N 10005 stack<int> sta; vector<int> mp ; int dfn ,low ,vis ,num ,degree ; int n,m,cnt,id,ans; void init(){ cnt=0; id=0; ans=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); memset(degree,0,sizeof(degree)); while(!sta.empty()) sta.pop(); for(int i=1;i<=n;i++) mp[i].clear(); } void tarjan(int x){ dfn[x]=low[x]=++id; sta.push(x); vis[x]=1; for(int i=0;i<mp[x].size();i++){ int t=mp[x][i]; if(!dfn[t]) { tarjan(t); low[x]=min(low[x],low[t]); }else if(vis[t]) low[x]=min(low[x],dfn[t]); } if(dfn[x]==low[x]){ int tp; cnt++; do{ tp=sta.top(); vis[tp]=0; num[tp]=cnt; sta.pop(); }while(tp!=x); } } void slove(){ int sum=0,index; for(int i=1;i<=n;i++){ for(int j=0;j<mp[i].size();j++){ if(num[i]!=num[mp[i][j]]) degree[num[i]]++; } } for(int i=1;i<=cnt;i++){ if(!degree[i]) sum++,index=i; } if(sum>1) cout<<"0"<<endl; else { for(int i=1;i<=n;i++) if(num[i]==index) ans++; cout<<ans<<endl; } } int main(){ while(cin>>n>>m){ init(); for(int i=0;i<m;i++){ int a,b; cin>>a>>b; mp[a].push_back(b); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); slove(); } }
相关文章推荐
- POJ 2186 Popular Cows(Tarjan + 强连通分量缩点)
- POJ 2186 Popular Cows(强连通分量缩点)
- POJ 2186:Popular Cows Tarjan模板题
- POJ 2186 Popular Cows 强连通分量 Kosaraju or tarjan
- poj 2186 Popular Cows(找出度为0的点)
- POJ 2186 Popular Cows --强连通分量
- 有向图的汇点 -- 兼 ACM PKU POJ 2186 ( Popular Cows ) 解题报告
- poj 2186 Popular Cows
- POJ 2186:Popular Cows(tarjan算法入门题)
- POJ 2186-Popular Cows:强连通分量问题
- poj 2186 Popular Cows
- POJ 2186 Popular Cows(强连通分量模板题)
- poj_2186 Popular Cows(强连通分量)
- poj 2186 Popular Cows (强连通分量,缩点)
- [ACM] POJ 2186 Popular Cows (强连通分量,Kosaraju算法知识整理)
- poj 2186【Popular Cows】1236【Network of Schools】2553【The Bottom of a Graph】
- POJ 2186 Popular Cows
- poj 2186 Popular Cows(强连通分量)
- POJ2186--Popular Cows
- poj 2186 Popular Cows (Tarjan 强连通分量+压缩点)