POJ 2186 Popular Cows tarjan+缩点

http://poj.org/problem?id=2186

题意:牛搞个人崇拜(怎么又是牛??牛很圣神?),还具有传递性 如果A崇拜B  B崇拜C 则A崇拜 C ,求受所有牛崇拜的牛的数量

解法:在强连通分量里面,每个牛相互崇拜,把强连通分量缩为一个点,缩点后的图 为一个强连通分量 或者

一个 弱连通分量 总之最后出度为零的缩点 受所有的牛崇拜

有一个地方:缩点时候可能会出现 多条同向的重边

  缩点后   第一个缩点 到第二个缩点 有两条有向线

 

所以最后用 in[]入度不好求  out[]为0的点只有一个的时候就找到答案了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#define Min(a,b)a<b?a:b
#define nMAX 10005
#define mMAX 50005
using namespace std;
int head[nMAX],dfn[nMAX],low[nMAX],stack[nMAX],node_sta[nMAX];
int out[nMAX],belon[nMAX];
int n,top,s_edge,atype,times;
bool insta[nMAX];
struct Edge
{
    int to,next;
}edge[mMAX];

void addedge(int u,int v)
{
    s_edge++;
    edge[s_edge].to=v;
    edge[s_edge].next=head[u];
    head[u]=s_edge;
    return ;
}

void tarjan(int u)
{
    dfn[u]=++times;
    low[u]=times;

    stack[++top]=u;
    insta[u]=1;
    int e,v;
    for(e=head[u];e;e=edge[e].next)
    {
        v=edge[e].to;
        if(!dfn[v])
        {
          tarjan(v);
          low[u]=Min(low[u],low[v]);
        }
        else if(insta[v])
            low[u]=Min(low[u],dfn[v]);
    }

    int j;
    if(low[u]==dfn[u])
    {
        atype++;
        do
        {
            j=stack[top--];
            insta[j]=0;
            belon[j]=atype;
            node_sta[atype]++;
        }while(j!=u);
    }
    return ;
}

void init()
{
    s_edge=0;
    top=0;
    atype=0;
    times=0;
    memset(head,0,sizeof(head));
    memset(insta,0,sizeof(insta));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(node_sta,0,sizeof(node_sta));
    memset(belon,0,sizeof(belon));
    memset(out,0,sizeof(out));
    return ;
}

int main()
{
    int m,u,v,i;
    while(~scanf("%d%d",&n,&m))
    {
       init();
       while(m--)
       {
           scanf("%d%d",&u,&v);
           addedge(u,v);
       }
       for(i=1;i<=n;i++)
           if(!dfn[i])
              tarjan(i);

      //缩点
      int e,v;
      for(i=1;i<=n;i++)
          for(e=head[i];e;e=edge[e].next)
          {
              v=edge[e].to;
              if(belon[i]!=belon[v])
                  out[belon[i]]++;
          }

        int ans=0,num=0;
        for(i=1;i<=atype;i++)
            if(out[i]==0)
            {
                ans=node_sta[i];
                num++;
            }
         if(num>1)
         printf("0\n");
         else
         printf("%d\n",ans);
    }
    return 0;
}

  

posted @ 2012-02-10 06:04  快乐.  阅读(184)  评论(0编辑  收藏  举报