zoukankan      html  css  js  c++  java
  • 经典的图论算法,C++描述

    #include < cstring >
    // 常量定义:
    const   int  maxV = 100 ;
    const   double  Inf = 1e100;
    // const int Inf=2000000000;
    // Graph类定义:
    template < class  T >
    struct  GraphMatrix {
         int  v;     // 顶点数
         int  e;     // 边数
        T a[maxV][maxV];     // 邻接矩阵
         void  init() {
            memset(a, 0 , sizeof (a));
        }
         void  clear() {
             int  i,j;
             for (i = 0 ; i < v;  ++ i) {
                 for (j = 0 ; j < v;  ++ j)
                    a[i][j] = Inf;
            }
        }
    } ;
    
    #include < list >
    using  std::list;
    template < class  T >
    struct  GraphList {
         int  v;
         int  e;
        list < T >  a[maxV];     // 邻接表
         void  clear() { // clear()应在更改v之前进行
             int  i;
             for (i = 0 ; i < v; i ++ )
                a[i].clear();
        }
         ~ GraphList() {
            v = maxV;
            clear();
        }
    } ;
    
    namespace  bridgeNS {
    /* 解决:查找、打印桥
     *算法:DFS——O(E)
     *输入:连通图(表):g
     *输出:屏幕
      */
        GraphList < int >  g;
         int  cnt;
         int  pre[maxV];     // DFS顺序
         int  low[maxV];     // 最低前序编号:儿子low值的最小值
         void  _bridge( int  prnt,  int  w) {
             int  v; // son
            low[w] = pre[w] = cnt ++ ;
            std::list < int > ::iterator li;
             for (li = g.a[w].begin(); li != g.a[w].end();  ++ li) {
                v =* li;
                 if (pre[v] ==- 1 ) {
                    _bridge(w,v);
                     if (low[w]  >  low[v]) low[w]  =  low[v];
                     if (low[v]  ==  pre[v])
                        printf( " %d-%d/n " ,w,v); // 找到桥
                } else   if (v != prnt  &&  low[w]  >  pre[v]) low[w]  =  pre[v];
            }
        }
         void  bridge() {
            cnt = 0 ;
            memset(pre, - 1 , sizeof (pre));
            _bridge( - 1 , 0 );
        }
    }         
    
    namespace  GabowNS {
    /* 解决:强分量
     *算法:Gabow——O(E)
     *输入:图(表):g
     *输出:分量编号sc[]
      */
        GraphList < int >  g;
         int  cnt0, cnt1;
         int  sc[maxV]; // 分量编号
         int  pre[maxV];     // DFS顺序
         int  path[maxV],pp; // path栈
         int  stack[maxV],sp; //
    
         void  _SCdfsR( int  w) {
            pre[w] = cnt0 ++ ;
            stack[sp ++ ] = w;
            path[pp ++ ] = w;
             int  v; std::list < int > ::iterator li;
             for (li = g.a[w].begin(); li != g.a[w].end();  ++ li) {
                v =* li;
                 if (pre[v] ==- 1 ) _SCdfsR(v);
                 else   if (sc[v] ==- 1 ) {
                     while (pre[path[pp - 1 ]]  >  pre[v])  -- pp;
                }
            }
             if (path[pp - 1 ]  !=  w)  return ;
             -- pp;
             do {
                sc[stack[ -- sp]] = cnt1;
            } while (stack[sp]  !=  w);
             ++ cnt1;
        }
         void  init() {
            memset(pre, - 1 , sizeof (pre));
            memset(sc, - 1 , sizeof (sc));
            cnt0 = cnt1 = 0 ;
            sp = pp = 0 ;
             int  i;
             for (i = 0 ; i < g.v;  ++ i) {
                 if (sc[i] ==- 1 )
                    _SCdfsR(i);
            }
        }
    
         bool  isStrongReach( int  s,  int  t) {
             return  sc[s] == sc[t];
        }
    }
    
    namespace  PrimNS {
    /* 解决:最小生成树MST
     *算法:Prim——O(V^2)
     *输入:加权连通图(矩阵):g
     *输出:父节点st[],与其父之边的权重wt[]
      */
        GraphMatrix < double >  g;
         int  st[maxV];     // MST节点之父——用以保存MST
         double  wt[maxV + 1 ];     // 与其父的边的权重
         int  fr[maxV];     // 非树顶点的最近树顶点
         void  mst() {
             int  v, w, min;
             for (v = 0 ; v < g.v;  ++ v) {
                st[v] =- 1 ; fr[v] = v; wt[v] = Inf;
            }
            st[ 0 ] = 0 ; wt[g.v] = Inf;
             for (min = 0 ; min != g.v;) {
                v = min; st[v] = fr[v];
                 for (w = 0 , min = g.v; w < g.v;  ++ w) {
                     if (st[w] ==- 1 ) {
                         if (g.a[v][w]  <  wt[w])
                            wt[w] = g.a[v][w], fr[w] = v;
                         if (wt[w]  <  wt[min])
                            min = w;
                    }
                }
            }
        }
    }
        
    namespace  DijkstraNS {  
    /* 解决:非负权图单源最短路径树SPT
     *算法:Dijkstra——O(V^2)
     *输入:加权连通图(矩阵):g
     *输出:父节点st[],与其父之边的权重wt[]
      */
        GraphMatrix < double >  g;
         int  st[maxV];    
         double  wt[maxV + 1 ];    
         int  fr[maxV];     // 非树顶点的最近树顶点
         void  spt( int  s) {
             int  v, w, min;
             for (v = 0 ; v < g.v;  ++ v) {
                st[v] =- 1 ; fr[v] = v; wt[v] = Inf;
            }
            st[s] = s; wt[g.v] = Inf; wt[s] = 0 ;
             for (min = s; min != g.v;) {
                v = min; st[v] = fr[v];
                 for (w = 0 , min = g.v; w < g.v;  ++ w) {
                     if (st[w] ==- 1 ) {
                         if (g.a[v][w] != Inf  &&  wt[v] + g.a[v][w]  <  wt[w])
                            wt[w] = wt[v] + g.a[v][w], fr[w] = v;
                         if (wt[w]  <  wt[min])
                            min = w;
                    }
                }
            }
        }
    }
    /**/
    namespace  FloydNS { //   
    /* 解决:所有点对最短路径
     *算法:Floyd——O(V^3)
     *输入:加权连通图(矩阵):g
     *输出:最短距离长度矩阵d[][], 路径矩阵p[][]
      */
        GraphMatrix < double >  g;
         double  d[maxV][maxV];     // 最短路径长度
         int  p[maxV][maxV];         // 最短路径下一顶点
         void  floyd() {
             int  i,s,t;
             for (s = 0 ; s < g.v;  ++ s) {
                 for (t = 0 ; t < g.v;  ++ t)
                     if ( (d[s][t]  =  g.a[s][t])  <  Inf)
                        p[s][t] = t;
                d[s][s] = 0 ;
            }
             for (i = 0 ; i < g.v;  ++ i)
                 for (s = 0 ; s < g.v;  ++ s)
                     if (s != i  &&  d[s][i]  <  Inf)
                         for (t = 0 ; t < g.v;  ++ t)
                             if (d[s][t]  >  d[s][i]  +  d[i][t]) {
                                d[s][t]  =  d[s][i]  +  d[i][t];
                                p[s][t]  =  p[s][i];
                            }
        }
    }
    namespace  TenshiNS { //
    /* 解决:二分图最大匹配
     *算法:匈牙利匹配(by Tenshi)——O(xv * yv)
     *输入:邻接矩阵g
     *输出:匹配数cnt,x匹配项xm[],y匹配项ym[]
     *备注:from Bug 06-07-07
      */
         int  xv,yv;     // 顶点数
         int  g[maxV][maxV];     // g[i][j]=1 表示 xi与yj相邻
         int  sy[maxV];     // 辅助:当轮被搜过的y点都是1 
         int  cnt,xm[maxV],ym[maxV];  // 输出 
         void  init() {
            cnt = 0 ;
            memset(g, 0 , sizeof (g));
            memset(xm, - 1 , sizeof (xm));
            memset(ym, - 1 , sizeof (ym));
        }
         bool  _path( int  u) // 返回是否找到增广路
         {
             for ( int  v = 0 ;v < yv;v ++ )  if (g[u][v]  &&   ! sy[v]) { sy[v] = 1 ;
                 if (ym[v] ==- 1   ||  _path(ym[v]))  { xm[u] = v; ym[v] = u;  return   1 ;}
            }   return   0 ;    
        }
         void  tenshi()
         {
             int  i;
             for (i = 0 ;i < xv;i ++ )
                 if (xm[i] ==- 1 ) {
                    memset(sy, 0 , sizeof (sy));
                    cnt += _path(i);
                }
        }  
    } 

    #include < cstring >
    // 常量定义:
    const   int  maxV = 100 ;
    const   double  Inf = 1e100;
    // const int Inf=2000000000;
    // Graph类定义:
    template < class  T >
    struct  GraphMatrix {
        
    int  v;     // 顶点数
         int  e;     // 边数
        T a[maxV][maxV];     // 邻接矩阵
         void  init() {
            memset(a,
    0 , sizeof (a));
        }

        
    void  clear() {
            
    int  i,j;
            
    for (i = 0 ; i < v;  ++ i) {
                
    for (j = 0 ; j < v;  ++ j)
                    a[i][j]
    = Inf;
            }

        }

    }
    ;

    #include
    < list >
    using  std::list;
    template
    < class  T >
    struct  GraphList {
        
    int  v;
        
    int  e;
        list
    < T >  a[maxV];     // 邻接表
         void  clear() { // clear()应在更改v之前进行
             int  i;
            
    for (i = 0 ; i < v; i ++ )
                a[i].clear();
        }

        
    ~ GraphList() {
            v
    = maxV;
            clear();
        }

    }
    ;

    namespace  bridgeNS {
    /* 解决:查找、打印桥
     *算法:DFS——O(E)
     *输入:连通图(表):g
     *输出:屏幕
     
    */

        GraphList
    < int >  g;
        
    int  cnt;
        
    int  pre[maxV];     // DFS顺序
         int  low[maxV];     // 最低前序编号:儿子low值的最小值
         void  _bridge( int  prnt,  int  w) {
            
    int  v; // son
            low[w] = pre[w] = cnt ++ ;
            std::list
    < int > ::iterator li;
            
    for (li = g.a[w].begin(); li != g.a[w].end();  ++ li) {
                v
    =* li;
                
    if (pre[v] ==- 1 ) {
                    _bridge(w,v);
                    
    if (low[w]  >  low[v]) low[w]  =  low[v];
                    
    if (low[v]  ==  pre[v])
                        printf(
    " %d-%d/n " ,w,v); // 找到桥
                }
    else   if (v != prnt  &&  low[w]  >  pre[v]) low[w]  =  pre[v];
            }

        }

        
    void  bridge() {
            cnt
    = 0 ;
            memset(pre,
    - 1 , sizeof (pre));
            _bridge(
    - 1 , 0 );
        }

    }
            

    namespace  GabowNS {
    /* 解决:强分量
     *算法:Gabow——O(E)
     *输入:图(表):g
     *输出:分量编号sc[]
     
    */

        GraphList
    < int >  g;
        
    int  cnt0, cnt1;
        
    int  sc[maxV]; // 分量编号
         int  pre[maxV];     // DFS顺序
         int  path[maxV],pp; // path栈
         int  stack[maxV],sp; //

        
    void  _SCdfsR( int  w) {
            pre[w]
    = cnt0 ++ ;
            stack[sp
    ++ ] = w;
            path[pp
    ++ ] = w;
            
    int  v; std::list < int > ::iterator li;
            
    for (li = g.a[w].begin(); li != g.a[w].end();  ++ li) {
                v
    =* li;
                
    if (pre[v] ==- 1 ) _SCdfsR(v);
                
    else   if (sc[v] ==- 1 ) {
                    
    while (pre[path[pp - 1 ]]  >  pre[v])  -- pp;
                }

            }

            
    if (path[pp - 1 !=  w)  return ;
            
    -- pp;
            
    do {
                sc[stack[
    -- sp]] = cnt1;
            }
    while (stack[sp]  !=  w);
            
    ++ cnt1;
        }

        
    void  init() {
            memset(pre,
    - 1 , sizeof (pre));
            memset(sc,
    - 1 , sizeof (sc));
            cnt0
    = cnt1 = 0 ;
            sp
    = pp = 0 ;
            
    int  i;
            
    for (i = 0 ; i < g.v;  ++ i) {
                
    if (sc[i] ==- 1 )
                    _SCdfsR(i);
            }

        }


        
    bool  isStrongReach( int  s,  int  t) {
            
    return  sc[s] == sc[t];
        }

    }


    namespace  PrimNS {
    /* 解决:最小生成树MST
     *算法:Prim——O(V^2)
     *输入:加权连通图(矩阵):g
     *输出:父节点st[],与其父之边的权重wt[]
     
    */

        GraphMatrix
    < double >  g;
        
    int  st[maxV];     // MST节点之父——用以保存MST
         double  wt[maxV + 1 ];     // 与其父的边的权重
         int  fr[maxV];     // 非树顶点的最近树顶点
         void  mst() {
            
    int  v, w, min;
            
    for (v = 0 ; v < g.v;  ++ v) {
                st[v]
    =- 1 ; fr[v] = v; wt[v] = Inf;
            }

            st[
    0 ] = 0 ; wt[g.v] = Inf;
            
    for (min = 0 ; min != g.v;) {
                v
    = min; st[v] = fr[v];
                
    for (w = 0 , min = g.v; w < g.v;  ++ w) {
                    
    if (st[w] ==- 1 ) {
                        
    if (g.a[v][w]  <  wt[w])
                            wt[w]
    = g.a[v][w], fr[w] = v;
                        
    if (wt[w]  <  wt[min])
                            min
    = w;
                    }

                }

            }

        }

    }

        
    namespace  DijkstraNS {  
    /* 解决:非负权图单源最短路径树SPT
     *算法:Dijkstra——O(V^2)
     *输入:加权连通图(矩阵):g
     *输出:父节点st[],与其父之边的权重wt[]
     
    */

        GraphMatrix
    < double >  g;
        
    int  st[maxV];    
        
    double  wt[maxV + 1 ];    
        
    int  fr[maxV];     // 非树顶点的最近树顶点
         void  spt( int  s) {
            
    int  v, w, min;
            
    for (v = 0 ; v < g.v;  ++ v) {
                st[v]
    =- 1 ; fr[v] = v; wt[v] = Inf;
            }

            st[s]
    = s; wt[g.v] = Inf; wt[s] = 0 ;
            
    for (min = s; min != g.v;) {
                v
    = min; st[v] = fr[v];
                
    for (w = 0 , min = g.v; w < g.v;  ++ w) {
                    
    if (st[w] ==- 1 ) {
                        
    if (g.a[v][w] != Inf  &&  wt[v] + g.a[v][w]  <  wt[w])
                            wt[w]
    = wt[v] + g.a[v][w], fr[w] = v;
                        
    if (wt[w]  <  wt[min])
                            min
    = w;
                    }

                }

            }

        }

    }

    /**/
    namespace  FloydNS { //   
    /* 解决:所有点对最短路径
     *算法:Floyd——O(V^3)
     *输入:加权连通图(矩阵):g
     *输出:最短距离长度矩阵d[][], 路径矩阵p[][]
     
    */

        GraphMatrix
    < double >  g;
        
    double  d[maxV][maxV];     // 最短路径长度
         int  p[maxV][maxV];         // 最短路径下一顶点
         void  floyd() {
            
    int  i,s,t;
            
    for (s = 0 ; s < g.v;  ++ s) {
                
    for (t = 0 ; t < g.v;  ++ t)
                    
    if ( (d[s][t]  =  g.a[s][t])  <  Inf)
                        p[s][t]
    = t;
                d[s][s]
    = 0 ;
            }

            
    for (i = 0 ; i < g.v;  ++ i)
                
    for (s = 0 ; s < g.v;  ++ s)
                    
    if (s != &&  d[s][i]  <  Inf)
                        
    for (t = 0 ; t < g.v;  ++ t)
                            
    if (d[s][t]  >  d[s][i]  +  d[i][t]) {
                                d[s][t] 
    =  d[s][i]  +  d[i][t];
                                p[s][t] 
    =  p[s][i];
                            }

        }

    }

    namespace  TenshiNS { //
    /* 解决:二分图最大匹配
     *算法:匈牙利匹配(by Tenshi)——O(xv * yv)
     *输入:邻接矩阵g
     *输出:匹配数cnt,x匹配项xm[],y匹配项ym[]
     *备注:from Bug 06-07-07
     
    */

        
    int  xv,yv;     // 顶点数
         int  g[maxV][maxV];     // g[i][j]=1 表示 xi与yj相邻
         int  sy[maxV];     // 辅助:当轮被搜过的y点都是1 
         int  cnt,xm[maxV],ym[maxV];  // 输出 
         void  init() {
            cnt
    = 0 ;
            memset(g,
    0 , sizeof (g));
            memset(xm,
    - 1 , sizeof (xm));
            memset(ym,
    - 1 , sizeof (ym));
        }

        
    bool  _path( int  u) // 返回是否找到增广路
         {
            
    for ( int  v = 0 ;v < yv;v ++ if (g[u][v]  &&   ! sy[v]) { sy[v] = 1 ;
                
    if (ym[v] ==- 1   ||  _path(ym[v]))  { xm[u] = v; ym[v] = u;  return   1 ;}
            }
      return   0 ;    
        }

        
    void  tenshi()
        
    {
            
    int  i;
            
    for (i = 0 ;i < xv;i ++ )
                
    if (xm[i] ==- 1 ) {
                    memset(sy,
    0 , sizeof (sy));
                    cnt
    += _path(i);
                }

        }
     
    }

  • 相关阅读:
    Debian / Ubuntu 更新内核并开启 TCP BBR 拥塞控制算法
    axios 常用的几个方法
    doT模板双重循环模板渲染方法
    利用闭包,在不设置全局变量的情况下,完成再次点击退出功能
    技术支持
    隐私政策
    apicloud踩坑集锦
    apicloud运行机制
    apcloud混合式开发app学习笔记
    bootstrap 弹出框 另类运用
  • 原文地址:https://www.cnblogs.com/topW2W/p/5150413.html
Copyright © 2011-2022 走看看