Popular Cows---poj2186(缩点,强联通)

题目链接:http://poj.org/problem?id=2186

求有多少个点满足其他n-1个点都能到达这个点,是单向图;

所以我们可以把图进行缩点,之后求出度为0的那个点内包含的点的个数就是求得答案;

如果出度为0的不止一个,那么答案为0;

 

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#define N 10010
#define Lson r*2
#define Rson r*2+1
#define INF 0xfffffff
using namespace std;

int Stack[N], top, Out[N], Time, flag;
int nBlock, Block[N], dfn[N], low[N], Is[N], n, Head[N], cnt;

struct Edge
{
    int v, next;
}e[N*N];
void Init()
{
    nBlock = cnt = top = Time = flag = 0;
    memset(Head, -1, sizeof(Head));
    memset(low, 0, sizeof(low));
    memset(dfn, 0, sizeof(dfn));
    memset(Block, 0, sizeof(Block));
    memset(Out, 0, sizeof(Out));
    memset(Is, 0, sizeof(Is));
    memset(Stack, 0, sizeof(Stack));
}
void Add(int u, int v)
{
    e[cnt].v=v;
    e[cnt].next=Head[u];
    Head[u]=cnt++;
}
void Tajar(int u)
{
    dfn[u]=low[u]=++Time;
    Is[u]=1;
    Stack[top++]=u;
    int v;
    for(int i=Head[u]; i!=-1; i=e[i].next)
    {
        v=e[i].v;
        if(!dfn[v])
        {
            Tajar(v);
            low[u]=min(low[u], low[v]);
        }
        else if(Is[v])
        {
            low[u]=min(low[u], dfn[v]);
        }
    }
    if(low[u]==dfn[u])
    {
        ++nBlock;
        do
        {
            v=Stack[--top];
            Is[v] = 0;
            Block[v]=nBlock;
        }while(u!=v);
    }
}
int main()
{
    int u, v, m;
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        Init();
        for(int i=0; i<m; i++)
        {
            scanf("%d%d", &u, &v);
            Add(u,v);
        }
        for(int i=1; i<=n; i++)
            if(!low[i])
            {
                Tajar(i);
            }
        for(int i=1; i<=n; i++)
        {
            for(int j=Head[i]; j!=-1; j=e[j].next)
            {
                u=Block[i]; v=Block[e[j].v];
                if(u!=v)
                    Out[u]++;
            }
        }
        flag=0;
        int Index;
        for(int i=1; i<=nBlock; i++)
        {
            if(Out[i]==0)
            {
                flag++;
                Index=i;
            }
        }
        if(flag>1)
        {
            printf("0\n");
            continue;
        }
        int ans=0;
        for(int i=1; i<=n; i++)
        {
            if(Block[i]==Index)
                ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2015-08-21 11:20  西瓜不懂柠檬的酸  Views(125)  Comments(0Edit  收藏  举报
levels of contents