本标程介绍了一些经典的图论算法,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); } } }