• 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;
    }
          
           
             
          

  • 相关阅读:
    HashMap源码分析
    静态代理和装饰模式的区别
    自动内存管理
    ReentrantReadWriteLock
    ReentranLock
    对象的内存布局
    对象的创建
    [P2495][SDOI2011]消耗战——虚树
    [HDU2966]In case of failure——KD树
    [Gym-101158J]Coverthe Polygon with Your Disk——梯度下降,模拟退火
  • 原文地址:https://www.cnblogs.com/csnd/p/12062712.html
Copyright © 2020-2023  润新知