【轉】經典的圖論演算法C++描述
阿新 • • 發佈:2018-12-31
#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]; //
// 常量定義:
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
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]; //