POJ 2186: Popular Cows

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


题意:

有一群绵羊,

现在有一些喜欢关系,喜欢关系是可以传递的。

问有多少绵羊直接或间接地被所有绵羊喜欢。


算法:

首先求强联通并缩点,方法见BYVoid的《有向图强连通分量的Tarjan算法》。

缩点之后形成了一个DAG。

现在来看一下有几个出度为0的块。

如果没有出度为0的块,

必然无解。

因为某个块有指向另一个块的边的话,那么那个块肯定就没有指向它的边或有向路径了,因为那样就形成了环。

如果出度为0的块多于一个,也无解。

因为显然从一个出度为零的块无法到达另一个出度为零的块。

如果有且只有一个出度为0的块,

这个块中的点即为解。


代码如下:

#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
const int MAXN=11000;
int tot,blkn;
int low[MAXN],dfsn[MAXN],blk[MAXN];
bool ins[MAXN],dex[MAXN];
vector<int>map[MAXN];
vector<int>blk_map[MAXN];
stack<int>ss;

void dfs(int u)
{
  dfsn[u]=tot++;
  ins[u]=true;
  low[u]=dfsn[u];
  ss.push(u);
  for(int i=0; i<map[u].size(); i++)
    {
      int v=map[u][i];
      if(dfsn[v]!=-1)
        {
          if(ins[v])
            {
              low[u]=min(low[u],dfsn[v]);
            }
        }
      else
        {
          dfs(v);
          low[u]=min(low[u],low[v]);
        }
    }
  if(dfsn[u]!=low[u])
    return;
  blkn++;
  while(!ss.empty())
    {
      int v=ss.top();
      ss.pop();
      ins[v]=false;
      blk[v]=blkn;
      if(v==u)break;
    }
  return;
}

void blk_dfs(int u)
{
  dfsn[u]=1;
  for(int i=0; i<blk_map[u].size(); i++)
    {
    	if(!dfsn[blk_map[u][i]])
      blk_dfs(blk_map[u][i]);
    }
  return;
}

int main()
{
  int n,m;
  while(~scanf("%d%d",&n,&m))
    {
      for(int i=0; i<n; i++)
        {
          map[i].clear();
          blk_map[i].clear();
        }
      memset(ins,0,sizeof(ins));
      memset(dex,0,sizeof(dex));
      memset(blk,-1,sizeof(blk));
      memset(dfsn,-1,sizeof(dfsn));
      while(!ss.empty())
        ss.pop();
      while(m--)
        {
          int u,v;
          scanf("%d%d",&u,&v);
          if(u==v)
            continue;
          u--;
          v--;
          map[v].push_back(u);
        }
      blkn=0;
      for(int i=0; i<n; i++)
        if(blk[i]==-1)
          {
            tot=0;
            dfs(i);
          }
      for(int i=0; i<n; i++)
        {
        	for(int j=0; j<map[i].size(); j++)
            {
            	int v=map[i][j];
              if(blk[i]==blk[v])continue;
              blk_map[blk[i]].push_back(blk[v]);
              dex[blk[v]]=true;
            }
        }
      int rt,cot=0;
      for(int i=1; i<=blkn; i++)
        {
          if(!dex[i])
          {
          rt=i;
          cot++;
          }
        }
      if(cot>1)
        {
          puts("0");
          continue;
        }
      memset(dfsn,0,sizeof(dfsn));
      blk_dfs(rt);
      {
        int i;
        for(i=1; i<=blkn; i++)
          {
            if(!dfsn[i])break;
          }
        if(i<=blkn)
          {
            puts("0");
            continue;
          }
      }
      int ans=0;
      for(int i=0; i<n; i++)
        {
          if(blk[i]==rt)
            {
              ans++;
            }
        }
      printf("%d\n",ans);
    }
  return 0;
}


你可能感兴趣的:(POJ 2186: Popular Cows)