POJ 2186 Popular Cows

题目大意:给定m条有向边,求出有多少点,以任意一个点为起始点时都能到达。

解题思路:Tarjan.

自己做了一个特别渣的Tarjan类,Tarjan题直接套模板就好了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;

#define MAXN 10100
#define MAXM 50100

struct PPP
{
       int point,next,val;
};

class Link
{
      public:
             int now[MAXN];
             struct PPP link[MAXM];
             void insert(int a,int b)
             {
                 tail++;
                 link[tail].point = b;
                 link[tail].next = now[a];
                 now[a] = tail;
             }
             void insert(int a,int b,int c)
             {
                 tail++;
                 link[tail].point = b;
                 link[tail].val = c;
                 link[tail].next = now[a];
                 now[a] = tail;
             }
             void clear()
             {
                  memset(now,0,sizeof(now));
                  memset(link,0,sizeof(link));
                  tail = 0;
             }
      private:
              int tail;
};
int d[MAXN];
int n,m;

class Tarjan
{
      private:
              int low[MAXN],dfn[MAXN];
              int ins[MAXN],stack[MAXN],belong[MAXN];
              int deep,top;
void dfs(int u)
{
     int v;
     deep++;
     low[u] = deep;
     dfn[u] = deep;
     stack[++top] = u;
     ins[u] = 1;
     for (int i = list1.now[u] ; i != 0 ; i = list1.link[i].next)
     {
         v = list1.link[i].point;
         if (!dfn[v]) {
                       dfs(v);
                       low[u] = min(low[u],low[v]);//low[u]<low[v]?low[u]:low[v];
                      }
                 else {
                       if (ins[v]) {
                                    low[u] = min(low[u],dfn[v]);//low[u]<dfn[v]?low[u]:dfn[v];
                                   }
                      }
     }
     if (low[u] == dfn[u]) {
                            length++;
                            do
                            {
                                   v = stack[top--];
                                   belong[v] = length;
                                   ins[v] = 0;
                            }while (u != v);
                           }
}
void rebuild()
{
     //新表对于权值的含义 
     for (int i = 1 ; i <= n ; i ++) weight[belong[i]] ++;
     for (int u = 1 ; u <= n ; u ++)
     {
         for (int e = list1.now[u] ; e != 0 ; e = list1.link[e].next)
         {
             int v = list1.link[e].point;
             if (belong[u] != belong[v])
             {
                list2.insert(belong[u],belong[v],weight[belong[u]]);
             }
         }
     }
}

      public:
             int weight[MAXN];
             int length;
             Link list1,list2;
             void clear()
             {
                  list1.clear();
                  list2.clear();
                  memset(low,0,sizeof(low));
                  memset(dfn,0,sizeof(dfn));
                  memset(ins,0,sizeof(ins));
                  memset(weight,0,sizeof(weight));
                  memset(stack,0,sizeof(stack));
                  memset(belong,0,sizeof(belong));
                  deep = top = length = 0;
             }
             void work()
             {
                  for (int i = 1 ; i <= n ; i ++)
                      if (!dfn[i]) {
                                    dfs(i);
                                   }
                  rebuild();
             }
             void insert(int a,int b)       {list1.insert(a,b);}
             void insert(int a,int b,int c) {list1.insert(a,b,c);}
}tarjan;

int main()
{
    int t;
    int x,y;
    while (scanf("%d%d",&n,&m) != EOF)
    {
          memset(d,0,sizeof(d));
          tarjan.clear();
          for (int i = 1 ; i <= m ; i ++)
          {
              scanf("%d%d",&x,&y);
              tarjan.insert(x,y);
          }
          tarjan.work();
          int ans = 0;
          int boo = 0;
          int temp;
          for (int i = 1 ; i <= tarjan.length ; i ++)
          {
              temp = 0;
              for (int j = tarjan.list2.now[i];j != 0 ; j = tarjan.list2.link[j].next)
                  temp ++;
              if (temp == 0) {
                              ans += tarjan.weight[i];
                              boo++;
                             }
          }
          if (boo == 1) printf("%d\n",ans);
                   else printf("0\n",ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值