POj 2186 Popular Cows[连通分量]

题目大意:给出N头牛,有M种关系u, v。代表u牛崇拜v牛。要求找出有多少头牛被所有牛崇拜着
题目链接:http://poj.org/problem?id=2186
解题思路:
1>求出强连通分量,标记每头牛属于哪个分量内
2>进行缩点,计算连通分量的个数x,给出的M组关系重新构图。u,v若属不于一个连通分量内out[belong[u]]++;
3>统计x个连通分量出度。如果超过1个的连通分量出度为0,证明两群牛互不崇拜;
   如果等于1 答案就是该分量中牛的个数.

代码如下:

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 10005
#define M 50005
struct Edge
{
    int v, next;
}edge[M];

int node[N], stack[N], instack[N], dfn[N], out[N];
int low[N], belong[N], index, cnt_edge, n, m, cnt_tar, top;
int ee[M][2];

void add_Edge(int u, int v)
{
    edge[cnt_edge].next=node[u];
    edge[cnt_edge].v=v;
    node[u]=cnt_edge++;
}
void tarjan(int u)
{
    int i, j, v;
    dfn[u]=low[u]=++index;
    stack[++top]=u;
    instack[u]=1;
    for(i=node[u]; i!=-1; i=edge[i].next)
    {
        v=edge[i].v;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u], low[v]);
        }
        else if(instack[v])
            low[u]=min(low[u], dfn[v]);
    }
    if(dfn[u]==low[u])
    {
        cnt_tar++;
        do
        {
            j=stack[top--];
            instack[j]=0;
            belong[j]=cnt_tar;
        }while(j!=u);
    }

}
void solve()
{
    int i;
    top=0, index=0, cnt_tar=0;
    memset(dfn, 0, sizeof(dfn));
    memset(low, 0, sizeof(low));
    for(i=1; i<=n; i++)
        if(!dfn[i])
            tarjan(i);
}
int main()
{
    int i, u, v;
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        cnt_edge=0;
        memset(node, -1, sizeof(node));
        for(i=1; i<=m; i++)
        {
            scanf("%d%d", &u, &v);
            ee[i][0]=u, ee[i][1]=v;
            add_Edge(u, v);
        }
        solve();
        for(i=1; i<=m; i++)
        {
            int xx=belong[ee[i][0]], yy=belong[ee[i][1]];
            if(xx!=yy)
                out[xx]++;
        }
        int mark=0, tot=0;
        for(i=1; i<=cnt_tar; i++)
            if(out[i]==0)
            {
                tot++;
                mark=i;
            }
        if(tot>1)
            printf("0\n");
        else if(tot==1)
        {
            tot=0;
            for(i=1; i<=n; i++)
                if(belong[i]==mark)
                    tot++;
            printf("%d\n", tot);
        }
    }
    return 0;
}
View Code

 

posted on 2013-07-30 22:46  crying_Dream  阅读(198)  评论(0编辑  收藏  举报