POJ2553 强连通出度为0的应用

题意:
      给你一个有向图,然后问你有多少个满足要求的点,要求是: 这个点能走到的所有点都能走回这个点,找到所有的这样的点,然后排序输出。


思路:

      可以直接一遍强连通缩点,所点之后出度为0的强连通点中所包含的点都是满足要求的,比较容易理解,在强连通里,所有点都能走回来,同时只要强连通所点后没有出度,那么就能保证里面的每个点到所有连接自己连接的点后都能走回来,还有就是这个题目我数组开到快 80000000了,还没MLE,这个我就不说什么了。


#include<stdio.h>
#include<string.h>
#include<stack>
#include<algorithm>

#define N_node 5001
#define N_edge 5000 * 5000 + 1

using namespace std;

typedef struct
{
   int to ,next;
}STAR;

typedef struct
{
   int a ,b;
}EDGE;

EDGE edge[N_edge];
STAR E1[N_edge] ,E2[N_edge];
int list1[N_node] ,list2[N_node] ,tot;
int Belong[N_node] ,Cnt;
int mark[N_node] ,Ans[N_node];
stack<int>sk;

void add(int a ,int b)
{
   E1[++tot].to = b;
   E1[tot].next = list1[a];
   list1[a] = tot;
   
   E2[tot].to = a;
   E2[tot].next = list2[b];
   list2[b] = tot;
}

void DFS1(int x)
{
   mark[x] = 1;
   for(int k = list1[x] ;k ;k = E1[k].next)
   {
      int to = E1[k].to;
      if(mark[to]) continue;
      DFS1(to);
   }
   sk.push(x);
}

void DFS2(int x)
{
   mark[x] = 1;
   Belong[x] = Cnt;
   for(int k = list2[x] ;k ;k = E2[k].next)
   {
      int to = E2[k].to;
      if(mark[to]) continue;
      DFS2(to);
   }
}

int main ()
{
   int n ,m ,i ,a ,b;
   while(~scanf("%d" ,&n) && n)
   {
      scanf("%d" ,&m);
      memset(list1 ,0 ,sizeof(list1));
      memset(list2 ,0 ,sizeof(list2));
      tot = 1;
      for(i = 1 ;i <= m ;i ++)
      {
         scanf("%d %d" ,&a ,&b);
         edge[i].a = a ,edge[i].b = b;
         add(a ,b);
      }
      memset(mark ,0 ,sizeof(mark));
      while(!sk.empty()) sk.pop();
      for(i = 1 ;i <= n ;i ++)
      if(!mark[i]) DFS1(i);
      
      memset(mark ,0 ,sizeof(mark));
      Cnt = 0;
      while(!sk.empty())
      {
         int xin = sk.top();
         sk.pop();
         if(mark[xin]) continue;
         Cnt ++;
         DFS2(xin);
      }
      
      memset(mark ,0 ,sizeof(mark));
      for(i = 1 ;i <= m ;i ++)
      {
         a = Belong[edge[i].a];
         b = Belong[edge[i].b];
         if(a == b) continue;
         mark[a] ++;
      }
      
    
      int nowid = 0;
      for(i = 1 ;i <= n ;i ++)
      if(!mark[Belong[i]]) Ans[++nowid] = i;
      sort(Ans + 1 ,Ans + nowid + 1);
      for(i = 1 ;i <= nowid ;i ++)
      if(i == nowid) printf("%d
" ,Ans[i]);
      else printf("%d " ,Ans[i]);
   }
   return 0;
}
      
       
         
      

原文地址:https://www.cnblogs.com/csnd/p/12062713.html