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

POJ 2186 Popular Cows【强连通Kosaraju+缩点】

2016-06-08 16:30 399 查看
Popular Cows
Time Limit: 2000MS

 

Memory Limit: 65536K

Total Submissions: 29593

 

Accepted: 11981

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

Hint

Cow 3 is the only cow of high popularity. 

Source

USACO 2003 Fall

 

题目大意:给你n头牛,m个关系,每个关系表示a崇拜b,问有多少牛被所有牛所崇拜。

思路:

根据样例可以看出,这个图不是DAG图,而是存在环的有向图,这里怎样处理留到之后来讨论,我们先讨论如何得出结论。

1、如果有这样一个DAG图:



(在DAG图中)我们不难分析,如果其点有出度,那么这个点首先一定就不是被所有牛崇拜的对象,所以如果一个点没有出度,那么这头牛就很有可能被所有牛所崇拜。根据这个图我们还能推出这样一个结论:如果出度为0的牛大于两个,那么就说明被所有牛都崇拜的个数为0,因为这里有两头及以上牛互相没有崇拜关系。

那么如果图变成了这样:



这个时候4就是被所有牛崇拜的对象。

综上所述,在DAG图中,出度为0的节点如果只有一个,那么这个节点就一定是被所有牛崇拜的对象,如果出度为0的节点为0或者是出度为0的节点个数大于等于2,那么就没有牛满足被所有牛崇拜的条件,也就是被所有牛崇拜的牛的个数为0.

2、处理有向环。

这个时候我们做题的目标性就很明确了,如何将一个带有向环的图变成一个DAG图,如果大家有对最小树型图之类的需要缩点的算法有所了解的话,相信大家已经明确了答案,对于一个环,我们可以当做一个点来处理。对于一个有向环,他们其中每两个节点又是强连通的,而且强连通算法又是辣么的快速 ,所以我们这里就使用强连通算法来确定强连通分量(有向环),并在处理过程中,将一个环染色,也就是将一堆点变成了一个点,这样,我们就得到了DAG图。

既然我们这样处理就得到了DAG图,那么AC也就近在眼前了。

3、代码实现

我这里求强连通分量的算法使用的是Kosaraju,两次Dfs,过程中染色,对于每个缩点,不用计较其出边的个数,要不然我们在这里要处理更多麻烦的步骤,我们要统计的是出度为0的点的个数,出度为1,还是出度为20,我们都不关心,所以在这里缩点之后边的缩减我这里就不进行处理了。

AC代码:

#include<stdio.h>
#include<string.h>
using namespace std;
int head[100000];
int head2[100000];
struct EdgeNode
{
int from;
int to;
int next;
}e[100000],ee[100000];
int n,m,cont,cont2,sig;
int degree[1000000];
int vis[1000000];
int num[1000000];
int color[1000000];
void add(int from,int to)
{
e[cont].from=from;
e[cont].to=to;
e[cont].next=head[from];
head[from]=cont++;
}
void add2(int from,int to)
{
ee[cont2].from=from;
ee[cont2].to=to;
ee[cont2].next=head2[from];
head2[from]=cont2++;
}
void Dfs(int u)
{
vis[u]=1;
for(int k=head[u];k!=-1;k=e[k].next)
{
int v=e[k].to;
if(vis[v]==0)
{
Dfs(v);
}
}
num[sig++]=u;
}
void Dfs2(int u)
{
vis[u]=1;
color[u]=sig;
for(int k=head2[u];k!=-1;k=ee[k].next)
{
int v=ee[k].to;
if(vis[v]==0)
{
Dfs2(v);
}
}
}
void Kosaraju()
{
sig=1;
memset(color,0,sizeof(color));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
{
Dfs(i);
}
}
sig=0;
memset(vis,0,sizeof(vis));
for(int i=n;i>=1;i--)
{
if(vis[num[i]]==0)
{
sig++;
Dfs2(num[i]);
}
}
for(int i=1;i<=n;i++)
{
for(int k=head[i];k!=-1;k=e[k].next)
{
int vv=e[k].to;
if(color[vv]!=color[i])
{
degree[color[i]]++;
}
}
}
int tot=0;
int tmp=-1;
for(int i=1;i<=sig;i++)
{
if(degree[i]==0)
{
tot++;
tmp=i;
}
}
if(tot==1)
{
int output=0;
for(int i=1;i<=n;i++)
{
if(color[i]==tmp)output++;
}
printf("%d\n",output);
}
else printf("0\n");
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
cont=0;cont2=0;
memset(num,0,sizeof(num));
memset(degree,0,sizeof(degree));
memset(vis,0,sizeof(vis));
memset(color,0,sizeof(color));
memset(head,-1,sizeof(head));
memset(head2,-1,sizeof(head2));
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add2(y,x);
}
Kosaraju();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  POJ 2186 pku 2186