POJ 2186 Popular Cows

抽象成:在一个有向图中,找所有的点都可以到达的点的个数

根据题意结果必在一个强连通分量里(所有的答案之间肯定互相能到达)。用tarjan找出所有的连通分量,如果某个连通分量里有连到外面的边,则这个分量肯定不会是答案(分量图是有向的无环图,从分量1里连线到分量2中的边,分量2肯定没有变连回分量1,也就是1到达了2但是2不能到达1)。如果没有向外连边的连通分量不是1个就没有答案。



Popular Cows
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 21376   Accepted: 8732

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

[Submit]   [Go Back]   [Status]   [Discuss]




#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxV=11000,maxE=55000;

struct Edge
{
    int to,next;
}edge[maxE];

int Adj[maxV],Size;

void init()
{
    Size=0;
    memset(Adj,-1,sizeof(Adj));
}

void Add_Edge(int u,int v)
{
    edge[Size].to=v;
    edge[Size].next=Adj[u];
    Adj[u]=Size++;
}

int Low[maxV],DFN[maxV],Stack[maxV],Belong[maxV],num[maxV];
int Index,top,scc,n;

bool Instack[maxV];

void tarjan(int u)
{
    int v;
    Low[u]=DFN[u]=++Index;
    Stack[top++]=u;
    Instack[u]=true;

    for(int i=Adj[u];~i;i=edge[i].next)
    {
        v=edge[i].to;
        if(!DFN[v])
        {
            tarjan(v);
            Low[u]=min(Low[u],Low[v]);
        }
        else if(Instack[v])
        {
            Low[u]=min(Low[u],DFN[v]);
        }
    }

    if(Low[u]==DFN[u])
    {
        scc++;
        do
        {
            v=Stack[--top];
            Instack[v]=false;
            num[scc]++;
            Belong[v]=scc;
        }while(v!=u);
    }
}

int solve(int n)
{
    memset(DFN,0,sizeof(DFN));
    memset(Instack,false,sizeof(Instack));
    memset(num,0,sizeof(num));

    Index=scc=top=0;

    for(int i=1;i<=n;i++)
    {
        if(!DFN[i]) tarjan(i);
    }

    return scc;
}

bool yes[maxV];

int main()
{
  int m;
while(scanf("%d%d",&n,&m)!=EOF&&n)
{
    init();
    memset(yes,true,sizeof(yes));
    int a,b;
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&a,&b);
        Add_Edge(a,b);
    }
    int scc=solve(n);

    for(int i=1;i<=n;i++)
    {
        for(int j=Adj[i];~j;j=edge[j].next)
        {
            int v=edge[j].to,u=i;
            if(Belong[v]!=Belong[u])
            {
                yes[Belong[u]]=false;
            }
        }
    }

    int ans=0,tot=0;

    for(int i=1;i<=scc;i++)
    {
        if(yes[i])
        {
            tot++;
            ans+=num[i];
        }
    }

    if(tot!=1) ans=0;
    printf("%d\n",ans);
}
    return 0;
}


你可能感兴趣的:(Algorithm,强连通分量)