POJ2186 Popular Cows【Kosaraju】【强连通分量】

Popular Cows

Time Limit: 2000MS
Memory Limit: 65536K

Total Submissions: 24266Accepted: 9954

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)。

意思是牛A崇拜牛B。特别是,如果牛A崇拜牛B,牛B崇拜牛C,那么牛A也崇拜牛C。那么

问题来了:请计算出被所有牛崇拜的牛的个数。

思路:刚学的Kosaraju算法。考虑这道题,把崇拜关系(A,B)看做是一条有向边,并且,

我们发现牛的崇拜关系具有传递性。那么只要牛A有一条路径连向牛B,就可以判定牛A

崇拜牛B。于是,被所有牛崇拜的牛就是所有的点都存在一条路径连向它的有向路径。下

边简述下Kosaraju算法:

(1)对原图进行第一遍深度优先遍历,记录下每个节点的离开时间num[i]

(2)对原图的反向边构成的图进行第二遍深度优先遍历,从步骤(1)中离开时间最晚的点开

始。第(2)步中每搜索到一棵树都是一个强连通分量。用Hash[]把同一连通分量上的点缩

成一个点。

(3)缩点之后的图就构成了DAG(有向无环图),树的个数就是强连通分量的个数。

这道题中,将原图强连通分量缩点后构成了DAG,那么如果新图中出度为0的点只有一个,

则有解,为该出度为0的点的强连通分量中点的个数。若出度为0的点的个数不止一个,那

么无解。因为至少有两头牛互相不崇拜。

参考博文:http://blog.csdn.net/chang_mu/article/details/38709047

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 10010;
const int MAXM = 50050;

struct EdgeNode
{
    int to;
    int next1;
    int fr;
    int next2;
}Edges[MAXM];

int Head1[MAXN],Head2[MAXN],vis[MAXN];
int num[MAXN],Hash[MAXN],Count[MAXN],outdegree[MAXN];
int id;

void AddEdges(int u,int v)
{
    Edges[id].to = v;
    Edges[id].next1 = Head1[u];
    Head1[u] = id;
    Edges[id].fr = u;
    Edges[id].next2 = Head2[v];
    Head2[v] = id++;
}
//DFS第一遍,求出记录每个节点离开时间num[i]
void DfsOne(int cur,int& sig)
{
    vis[cur] = 1;
    for(int i = Head1[cur]; i != -1; i = Edges[i].next1)
    {
        if( !vis[Edges[i].to] )
            DfsOne(Edges[i].to,sig);
    }
    num[++sig] = cur;
}
//DFS第二遍,求出双联通分量
void DfsTwo(int cur,int sig)
{
    vis[cur] = 1;
    Hash[cur] = sig;    //Hash用来将同一个联通分量中的点缩成一个点
    Count[sig]++;
    for(int i = Head2[cur]; i != -1; i = Edges[i].next2)
    {
        if( !vis[Edges[i].fr])
            DfsTwo(Edges[i].fr,sig);
        else if(Hash[Edges[i].fr] != Hash[cur])     //outdegree判断缩点后新图各点是否有出度
            outdegree[Hash[Edges[i].fr]] = 1;
    }
}

int Kosaraju(int N)
{
    int sig = 0,ans;
    memset(vis,0,sizeof(vis));
    for(int i = 1; i <= N; ++i)
        if( !vis[i] )
            DfsOne(i,sig);

    memset(vis,0,sizeof(vis));
    memset(Count,0,sizeof(Count));
    memset(outdegree,0,sizeof(outdegree));

    int i = sig;
    sig = 0;
    for(; i >= 1; --i)
        if( !vis[num[i]])
            DfsTwo(num[i],++sig);

    int temp = 0;
    for(int i = 1; i <= sig; i++)   //新图只有一个点出度为0才算有解
        if(!outdegree[i])
        {
            temp++;
            ans = Count[i];
        }

    //printf("$%d ",temp);
    if(temp == 1)
        return ans;
    else
        return 0;
}

int main()
{
    int N,M,u,v;
    while(~scanf("%d%d",&N,&M))
    {
        id = 0;
        memset(Head1,-1,sizeof(Head1));
        memset(Head2,-1,sizeof(Head2));
        for(int i = 0; i < M; ++i)
        {
            scanf("%d%d",&u,&v);
            AddEdges(u,v);
        }
        int ans = Kosaraju(N);
        printf("%d\n",ans);
    }

    return 0;
}
时间: 2024-10-10 06:10:55

POJ2186 Popular Cows【Kosaraju】【强连通分量】的相关文章

POJ2186 Popular Cows 【强连通分量Kosaraju】

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23445   Accepted: 9605 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 &l

POJ2186 Popular Cows 【强连通分量】+【Kosaraju】+【Tarjan】+【Garbow】

Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23445   Accepted: 9605 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 &l

[POJ2186]Popular Cows(强连通分量)

题目链接:http://poj.org/problem?id=2186 给定n个点m条边,求某点使得其他点都有通向它的一条路径,计算这个点集的大小. 强连通分解后求出度为0的连通分量的个数,如果有且仅有一个连通分量出度为1,则统计这个连通分量中点的数目. 遍历所有点的出边指向的点,判断这两个点是否属于同一个连通分量,记录每个连通分量中的点的数目. 1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip&

POJ 2186 Popular Cows (强连通分量)

POJ 2186 Popular Cows 链接:http://poj.org/problem?id=2186 题意:每头奶牛都梦想着成为牧群中最受奶牛仰慕的奶牛.在牧群中,有N 头奶牛,1≤N≤10,000,给定M 对(1≤M≤50,000)有序对(A, B),表示A 仰慕B.由于仰慕关系具有传递性,也就是说,如果A 仰慕B,B 仰慕C,则A 也仰慕C,即使在给定的M 对关系中并没有(A, C).你的任务是计算牧群中受每头奶牛仰慕的奶牛数量. 思路:首先可以知道,在同一个强连通分量内的点一定互

poj 2186 Popular Cows 【强连通分量Tarjan算法 + 树问题】

题目地址:http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 27496   Accepted: 11059 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

POJ 2186:Popular Cows(强连通分量)

[题目链接] http://poj.org/problem?id=2186 [题目大意] 给出一张有向图,问能被所有点到达的点的数量 [题解] 我们发现能成为答案的,只有拓扑序最后的SCC中的所有点, 那么我们从其中一个点开始沿反图dfs,如果能访问到全图, 则答案为其所在SCC的大小,否则为0. [代码] #include <cstdio> #include <algorithm> #include <vector> #include <cstring>

强连通分量tarjan缩点——POJ2186 Popular Cows

这里的Tarjan是基于DFS,用于求有向图的强联通分量. 运用了一个点dfn时间戳和low的关系巧妙地判断出一个强联通分量,从而实现一次DFS即可求出所有的强联通分量. §有向图中, u可达v不一定意味着v可达u.    相互可达则属于同一个强连通分量    (Strongly Connected Component, SCC) §有向图和它的转置的强连通分量相同 §所有SCC构成一个DAG(有向无环图) dfn[u]为节点u搜索的次序编号(时间戳),即首次访问u的时间 low[u]为u或u的

poj2186 Popular Cows --- 强连通

给一个有向图,问有多少结点是其他所有结点都可以到达的. 等价于,在一个有向无环图上,找出度为0 的结点,如果出度为0的结点只有一个,那么这个就是答案,如果大于1个,则答案是0. 这题有环,所以先缩点.求唯一出度为0的强连通分量. #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<iostream> #define inf 0x3f3f3f3f

POJ2186 Popular Cows【Tarjan】【强连通分量】

题目连接: http://poj.org/problem?id=2186 题目大意: 每头奶牛都希望自己成为最欢迎的那头牛.给你N头牛,M个崇拜关系(A,B).意思是牛A 崇拜牛B.特别是,如果牛A崇拜牛B,牛B崇拜牛C,那么牛A也崇拜牛C.那么问题来了: 请计算出被所有牛崇拜的牛的个数. 思路: 把崇拜关系(A,B)看做是一条有向边,并且,我们发现牛的崇拜关系具有传递性.那么只要 牛A有一条路径连向牛B,就可以判定牛A崇拜牛B.于是,被所有牛崇拜的牛就是所有的点 都存在一条路径连向它的有向路径