1. 程式人生 > >【轉】經典的圖論演算法C++描述

【轉】經典的圖論演算法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];     //