POJ 2186 Popular Cows tarjan缩点 强连通分量

题目大意:输入一行n,m代表n个牛,m个关系,下面m行每行两个数字u和v代表u仰慕v,如果a仰慕b,b仰慕c那么a仰慕c,问是否有牛被所有的其他牛仰慕,这样的牛的数量是多少。

思路:如果一个牛被其他所有牛仰慕,那么这个牛所在的强连通分量出度一定为0。所以我们要先缩点,把是一个强连通分量的牛看成一个整体。接下来我们依次判断一个牛所仰慕的其他牛是否和它是一个强连通分量,如果不是那么这个强连通分量的出度加一,并且这个强连通分量里的牛的数量不会是答案。之后我们扫一遍强连通分量的个数,看一下哪个强连通分量的出度是0,如果结果大于1那么不满足题意,否则输出那唯一一个出度为0的强连通分量里的个数。


几组样例:

3 0

0

3 2

1 2

2 3

1

6 6

1 2

2 3

3 1

4 5

5 6

6 4

0

代码如下:

#include
#include
#include
#include
#include
#include
#include
#include
#define inf 0x3fffffff
using namespace std;
const int maxn=11000;
int first[maxn],sign;
int low[maxn],dfn[maxn],Stack[maxn],belong[maxn];///belong  1~scc  判断第几个点属于哪个连通分量
int index,top;
int out[maxn];
int scc;///强连通分量的个数
int instack[maxn];///判断是否在栈里
int num[maxn];///各个强连通分量包含点的个数,数组编号1~scc
///num数组不一定需要,结合实际情况
struct node
{
    int to,w,next;
}edge[maxn*10];
void creat()
{
    memset(first,-1,sizeof(first));
    sign=0;
}
void add_edge(int u,int v,int w)
{
    edge[sign].to=v;
    edge[sign].w=w;
    edge[sign].next=first[u];
    first[u]=sign++;
}
void tarjan(int u)
{
    int to;
    low[u]=dfn[u]=++index;
    Stack[top++]=u;
    instack[u]=1;
    for(int i=first[u];~i;i=edge[i].next)
    {
        to=edge[i].to;
        if(!dfn[to])
        {
            tarjan(to);
            if(low[u]>low[to])
            {
                low[u]=low[to];
            }
        }
        else if(instack[to]&&low[u]>dfn[to])
        {
            low[u]=dfn[to];
        }
    }
    if(low[u]==dfn[u])
    {
        scc++;
        do
        {
            to=Stack[--top];
            instack[to]=0;
            belong[to]=scc;
            num[scc]++;
        }while(to!=u);
    }
}
int main()
{
    int n,m;
    int u,v,w;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        creat();
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        memset(belong,0,sizeof(belong));
        memset(Stack,0,sizeof(Stack));
        memset(instack,0,sizeof(instack));
        memset(num,0,sizeof(num));
        memset(out,0,sizeof(out));
        top=scc=index=0;
        for(int i=0;i1)
            puts("0");
        else
            printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(图论)