poj 2186 Popular Cows(korasaju)

题意:有N头牛 每一头牛都梦想着成为popular cow,(但这是不可能滴) 有m组仰慕的关系,仰慕有传递性 比如说A觉得B是popular and B thinks C is popular, then A thinks C is popalur also;
现在问有多少头牛是会被其他牛都仰慕。

思路:求强连通分量,缩成点 点内的头当然是相互仰慕的咯!! 然后求新的图 的出度 出度也0的点就会被所有牛仰慕 算出出度为0的强连通分量里点的个数就OK了,注意 可能有多个出度为0的点,这时输出0(不满足要求) 刚学korasaju 算法,所以用它做 详解见上一篇

92MS

#include <stdio.h>
#include <string.h>
#define VM 10005
#define EM 50005

struct E
{
      int to,next;
} edge1[EM],edge2[EM];
int head1[VM],head2[VM],p,n;
int scc_id[VM],vis[VM],order[VM],cnt,scc;
  int outdeg[VM],indeg[VM];
void addedge (int cu,int cv)
{
      edge1[p].to = cv;
      edge1[p].next = head1[cu];
      head1[cu] = p;
      edge2[p].to = cu;
      edge2[p].next = head2[cv];
      head2[cv] = p ++;
}

void dfs (int u)
{
      for (int i = head1[u]; i != -1; i = edge1[i].next)
      {
              int v = edge1[i].to;
              if (!vis[v])
              {
                      vis[v] = 1;
                      dfs(v);
              }
      }
      order[++cnt] = u;
}
void redfs (int u)
{
      for (int i = head2[u]; i != -1; i = edge2[i].next)
      {
              int v = edge2[i].to;
              if (!scc_id[v])
              {
                      scc_id[v] = scc;
                      redfs (v);
              }
      }
}
void korasaju ()
{
      int u,i;
      cnt = scc = 0;
      memset (vis,0,sizeof(vis));
      memset (scc_id,0,sizeof(scc_id));
      memset (order,0,sizeof(order));
      for (u = 1; u <= n; u ++)
              if (!vis[u])
              {
                      vis[u] = 1;
                      dfs(u);
              }
      for (i = n; i > 0; i --)
      {
              u = order[i];
              if (!scc_id[u])
              {
                      scc_id[u] = ++scc;
                      redfs (u);
              }
      }
}
void count_deg()
{
      memset(indeg, 0, sizeof(indeg));
      memset(outdeg, 0, sizeof(outdeg));
      for (int u=1; u<=n; ++u)
            for (int i=head1[u]; i!=-1; i=edge1[i].next)
            {
                  int v = edge1[i].to;
                  if (scc_id[u] != scc_id[v])
                  {
                        indeg[scc_id[v]]++;
                        outdeg[scc_id[u]]++;
                  }
            }

}
int main ()
{
      int m,u,v,i;
      scanf ("%d%d",&n,&m);
      memset (head1,-1,sizeof(head1));
      memset (head2,-1,sizeof(head2));
      p = 0;
      while (m --)
      {
              scanf ("%d%d",&u,&v);
              addedge (u,v);
      }
      korasaju ();
    count_deg();
    int count = 0,loc;
      for (i = 1;i <= scc;i ++)
              if (outdeg[i] == 0)
              {
                      ++count;
                      loc = i;
              }
      if (count > 1)
              printf ("0\n");
      else
      {
              count = 0;
              for (u = 1;u <= n;u ++)
                      if (scc_id[u] == loc)
                              ++count;
              printf ("%d\n",count);
      }

      return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值