码迷,mamicode.com
首页 > 编程语言 > 详细

经典的图论算法,C++描述

时间:2016-01-22 11:00:43      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:

#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);
技术分享            }

技术分享    }
 
技术分享}

经典的图论算法,C++描述

标签:

原文地址:http://www.cnblogs.com/topW2W/p/5150413.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!