您的位置:首页 > 运维架构

poj2186 Popular Cows

2016-11-30 20:54 288 查看
Popular Cows

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 31782 Accepted: 12909
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
3 3
1 2
2 1
2 3

Sample Output
1


今天学习了强连通分量,应该说找强连通分量的函数要比找双联通分量函数的要简单一些的。

大意:给你n头牛,然后有m对关系,每对关系(a,b)说的是a牛仰慕b牛。

牛的仰慕具有传递性,也就是说如果a->b,b->c,那么有a->c。

然后问你这群牛中有多少头牛是受到所有牛仰慕的。

思路:

因为仰慕关系具有传递性,因此在一个强连通分量中的顶点:其中一头牛A如果仰慕一头牛B,那么A所在的强连通分量中的所有顶点都对牛B仰慕。

首先就是找出所有的双连通分量然后我们把所有的强连通分量缩成一个点,并构造新图。

(具体强连通的求解我是按照大白书上学习的)

最后做一次扫描,统计出度为0的强连通分量的个数。

如果个数为1,说明该强连通分量中的所有顶点都是符合条件的。否则是没有符合条件的牛的。



对于示例,缩点过程就像这样,最终可以得到3这个顶点是符合条条件的。

如果还是不怎么懂,读者可以自己画图理解一下,留言也可以。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;
const int MAXN=10000+10;
int n,m;
int dfn[MAXN],sccno[MAXN],dfs_clock,scc_cnt;
typedef vector<int>ve;
vector<ve>G(MAXN);
stack<int>S;
int dfs(int u)
{
int lowu=dfn[u]=++dfs_clock;
S.push(u);
for(int i=0,l=G[u].size();i<l;++i)
{
int v=G[u][i];
if(!dfn[v])
{
int lowv=dfs(v);
lowu=min(lowu,lowv);
}
else if(!sccno[v])
{
lowu=min(lowu,dfn[v]);
}
}
if(lowu==dfn[u])
{
scc_cnt++;
while(1)
{
int x=S.top();
S.pop();
sccno[x]=scc_cnt;
if(x==u)break;
}
}
return lowu;
}

void find_scc()
{
dfs_clock=scc_cnt=0;
for(int i=0;i<n;++i)if(!dfn[i])dfs(i);
}

int out[MAXN];
int main()
{
int i,j,l;
scanf("%d%d",&n,&m);
int u,v;
while(m--)
{
scanf("%d%d",&u,&v);
u--;
v--;
G[u].push_back(v);
}
find_scc();//搜索并找出强连通分量
//缩点
int pos,ans=0;
for(i=0;i<n;++i)
for(j=0,l=G[i].size();j<l;++j)
{
int v=G[i][j];
if(sccno[i]!=sccno[v])
{
out[sccno[i]]++;
}
}
//统计出度为0的“顶点
for(i=1;i<=scc_cnt;++i)
{
if(!out[i])
{
pos=i;
ans++;
}
}
if(ans>1)puts("0");
else
{
int sum=0;
for(i=0;i<n;++i)
{
if(sccno[i]==pos)sum++;
}
printf("%d\n",sum);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 图论 强连通分量