zoukankan      html  css  js  c++  java
  • hdu3594 强连通 tarjan

    题意: 判断是不是强连通图 ,同时每一条边必须只能在一个环里


    思路:之前我的强连通用的全是双深搜,结果题目的第二个要求很难判断,一开始写了三个深搜加上并查集,结果越写越乱,其实就是在判断一个边是否只在一个环内搞不定,后来看了下网上的代码,用的全是tarjan,没办法了,又学习了一下tarjan算法,学完后发现这个算法不错,比双深搜快一倍的时间吧,他的时间复杂度是O(n + m) n是点m是边,tarjan算法的运行步骤为第二问的解决提供了条件,其中的stack,low,dfn配合的很好,我们要开一个数组记录搜索路径,然后当我们搜到一个点发现他被搜过同时他还在stack中的话,我们直接通过路径数组原路返回到他,把路上所有的点的次数都加1(开个数组记录次数),如果发现有大于1的直接就NO了,还有就是点有一个点的次数不要加1,就是查找路径的第一个点的上一个点,也是路径中的最后一个点(因为是环),这样就ok了.


    #include<stdio.h>
    #include<string.h>
    #include<stack>
                                   
    #define N_node 25000 + 1000
    #define N_edge 55000 + 1000


    using namespace std;


    typedef struct
    {
       int to ,next;
    }STAR;


    STAR E[N_edge];
    int list[N_node] ,tot;
    int mer[N_node];
    int count[N_node];
    int DFN[N_node] ,LOW[N_node];
    int Index ,num ,okk;
    int instack[N_node];
    stack<int>st; 


    void add(int a ,int b)
    {
       E[++tot].to = b;
       E[tot].next = list[a];
       list[a] = tot;
    }


    int minn(int x ,int y)
    {
       return x < y ? x : y;
    }


    void merge(int e ,int s)
    {
       while(mer[s] != e)
       {
          count[s] ++;
          if(count[s] >= 2)
          {
             okk = 1;
             return ;
          }
          s = mer[s];
       }
    }


    void Tarjan(int s)
    {
       if(okk) return;
       DFN[s] = LOW[s] =  Index ++;
       st.push(s);
       instack[s] = 1;
       for(int k = list[s] ;k ;k = E[k].next)
       {
          int to = E[k].to;
          if(!DFN[to])
          {
             mer[to] = s;
             Tarjan(to);
             LOW[s] = minn(LOW[to] ,LOW[s]);
          }
          else if(instack[to])
          {
             LOW[s] = minn(DFN[to] ,LOW[s]);
             merge(to ,s);
             if(okk) return;       
          }
       }
       if(LOW[s] == DFN[s])
       {
          num ++;
          if(num > 1) okk = 1;   
          while(1)
          {
             int v = st.top();
             st.pop();
             instack[v] = 0;
             if(v == s) break;
          }
       }
       return ;
    }
     
    int main ()
    {
       int t ,i ,n ,a ,b;
       scanf("%d" ,&t);
       while(t--)
       {
          scanf("%d" ,&n);
          memset(list ,0 ,sizeof(list));
          memset(instack ,0 ,sizeof(instack));
          memset(DFN ,0 ,sizeof(DFN));
          memset(LOW ,0 ,sizeof(LOW));
          memset(count ,0 ,sizeof(count));
          for(i = 0 ;i < n ;i ++)mer[i] = i;
          while(!st.empty()) st.pop();
          tot = Index = 1 ,num = 0;
          while(scanf("%d %d" ,&a ,&b) && a + b)
          {
             add(a ,b);
          }
          okk = 0;
          for(i = 0 ;i < n ;i ++)
          {
             if(okk) break;
             if(DFN[i]) continue;
             Tarjan(i);
          }
          if(okk) printf("NO ");
          else printf("YES ");
       }
       return 0;
    }
          
             
             

  • 相关阅读:
    poj 2488 DFS
    畅通工程 并查集模版
    KMP 模板
    poj 1426 DFS
    poj 2528 线段数
    poj 3468 线段数 修改区间(点)
    CVPR2012文章阅读(2)A Unified Approach to Salient Object Detection via Low Rank Matrix Recovery
    如何制定目标
    Saliency Map 最新综述
    计算机视觉模式识别重要会议杂志
  • 原文地址:https://www.cnblogs.com/csnd/p/12063299.html
Copyright © 2011-2022 走看看