### POJ 2186：Popular Cows（tarjan算法入門題）

A就會認為C是受歡迎的。你的任務是計算有多少牛讓其他所有牛都認為它是最受歡迎的。

8 9

1 2

2 3

3 4

4 5

5 3

5 6

6 7

7 8

8 6

POJ這個題目數據弱了，好多人說算法寫得不對也可AC，不過我覺得自己寫的是沒問題的，測試了

`#include <iostream>#include <stdio.h>#include <string.h>using namespace std;const int maxm = 600000;const int maxn = 200000;int head[maxn];       ///鏈表頭節點int Stack[maxn];      ///棧bool inStack[maxn];   ///用來標記節點是否在棧中int belong[maxn];     ///各個頂點所屬於的連通分量int dfn[maxn];        ///時間標記int low[maxn];        ///相當於並查集int outdegree[maxn];  ///統計頂點入度int edgeNumber,time,top,cnt;     ///time時間標記，top棧頂指針,cnt當前連通分量編號struct Edge{    int A;    int B;    int nex;}edge[maxm];void addEdge(int a,int b){    edge[edgeNumber].A = a;    edge[edgeNumber].B = b;    edge[edgeNumber].nex = head[a];    head[a] = edgeNumber++;}///強連通找各個連通分量所屬的集合void tarjan(int a){    dfn[a] = low[a] = ++time;    Stack[++top] = a;    inStack[a] = true;    for(int i = head[a]; i != -1; i = edge[i].nex)    {        int b = edge[i].B;        if(!dfn[b])  ///沒有被訪問過        {            tarjan(b);            low[a] = min(low[a],low[b]);        }        else if(inStack[b])        {            low[a] = min(low[a],dfn[b]);        }    }    if(dfn[a] == low[a])    {        cnt++;        int temp;        do        {            temp = Stack[top--];            inStack[temp] = false;            belong[temp] = cnt;     ///當前頂點屬於第cnt個連通分量        }while(temp != a);    }}void solve(int n,int m){    int a,b;    edgeNumber = 0;    memset(head,-1,sizeof(head));    for(int i = 1; i <= m; i++)    {        scanf("%d%d",&a,&b);        addEdge(a,b);    }    top = time = cnt = 0;    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(outdegree,0,sizeof(outdegree));    for(int i = 1; i <= n; i++)        inStack[i] = false;    for(int i = 1; i <= n; i++)    {        if(dfn[i]==0)            tarjan(i);    }    for(int i = 0; i < edgeNumber; i++)    {        a = edge[i].A;        b = edge[i].B;        a = belong[a];        b = belong[b];        if(a != b)  ///不屬於一個連通分量的話，我們統計出度            outdegree[a]++;    }    int num = 0;    int temp;    for(int i = 1; i <= cnt; i++)    {        if(outdegree[i]==0)        {            temp = i;            num++;        }    }    int ans = 0;    if(num == 1)  ///出度為1的點必須有且只能有一個    {        for(int i = 1; i <= n; i++)        {            if(belong[i] == temp)                ans++;        }    }    printf("%d\n",ans);}int main(){    int N,M;    while(~scanf("%d%d",&N,&M)) ///N頭牛，M個關系    {        solve(N,M);    }    return 0;}`