鱼C论坛

 找回密码
 立即注册
查看: 2647|回复: 8

[技术交流] 最小生成树算法,最短路径算法,网络流算法

[复制链接]
发表于 2014-2-8 22:33:46 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 andalousie 于 2014-3-16 08:38 编辑

大家万事如意,大家心想事成。这里给出最小生成树的两种算法的C++版本。这里来列一下清单
主测试文件:
MST.cpp
图的头文件和实现文件
graph.h graph.cc
Prim算法的补充文件
List.h list.cc //用于实现一个简易的双向循环链优先队列
Kruskal算法的补充文件
DisjointSet.h DisjointSet.cc //用于实现并查集

MST.cpp
  1. #include <iostream>
  2. #include "graph.h"

  3. int main(){   
  4.         /** Creates a graph with 12 vertices */
  5.     Graph g1(10);

  6.     /** Adds edges to the graph */
  7.     g1.addEdge(1, 2, 5); g1.addEdge(1, 3, 7);
  8.     g1.addEdge(2, 3, 9); g1.addEdge(2, 6, 6);
  9.     g1.addEdge(2, 5, 15); g1.addEdge(3, 4, 8);
  10.     g1.addEdge(3, 5, 7); g1.addEdge(4, 5, 5);
  11.     g1.addEdge(5, 6, 8); g1.addEdge(5, 7, 9);
  12.     g1.addEdge(6, 7, 11);

  13.     /** Explores all vertices findable from vertex 1 */
  14.     g1.Prim(2);
  15.     g1.Kruskal(2);
  16. }
复制代码
graph.h
  1. #if !defined (GRAPH_H)
  2. #define GRAPH_H

  3. /************************************************************

  4. Class Graph represents a Graph [V,E] having vertices V and
  5. edges E.

  6. ************************************************************/
  7. class Graph {
  8.     private:
  9.         int    _n;  /// n is the number of vertices in the graph
  10.         int ** _A;  /// A stores the edges between two vertices
  11.     public:
  12.         Graph(int size = 2);
  13.         ~Graph();
  14.         bool isConnected(int, int);
  15.         void addEdge(int x, int y, int d);
  16.         void Prim(int s);
  17.         void Kruskal(int s);
  18. };

  19. #endif
复制代码
graph.cc
  1. #include <iostream>
  2. #include "graph.h"
  3. #include "List.h"
  4. #include "DisjointSet.h"

  5. Graph::Graph(int size) {
  6.     int i, j;
  7.     if (size < 2) _n = 2;
  8.     else _n = size;
  9.     _A = new int*[_n];
  10.     for (i = 0; i < _n; ++i)
  11.         _A[i] = new int[_n];
  12.     for (i = 0; i < _n; ++i)
  13.         for (j = 0; j < _n; ++j)
  14.             _A[i][j] = 0;
  15. }

  16. Graph::~Graph() {
  17.     for (int i = 0; i < _n; ++i)
  18.     delete [] _A[i];
  19.     delete [] _A;
  20. }

  21. /******************************************************
  22. Checks if two given vertices are connected by an edge
  23. @param u vertex
  24. @param v vertex
  25. @return true if connected false if not connected
  26. ******************************************************/
  27. bool Graph::isConnected(int x, int y) {
  28.     return (_A[x-1][y-1] != 0);
  29. }

  30. /*****************************************************
  31. adds an edge E to the graph G.
  32. @param u vertex
  33. @param v vertex
  34. *****************************************************/
  35. void Graph::addEdge(int x, int y, int d) {
  36.     _A[x-1][y-1] = d; _A[y-1][x-1] = d;
  37. }

  38. /*****************************************************
  39. performs Prim's algorithm
  40. @param s initial vertex
  41. *****************************************************/
  42. void Graph::Prim(int s) {
  43.     Queue Q;

  44.     /** Keeps track of explored vertices */
  45.     int  *explored = new int [_n+1];
  46.     int  *grown    = new int [_n+1];
  47.     bool *done     = new bool[_n+1];

  48.     /** Initailized all vertices */
  49.     for (int i = 1; i <= _n; ++i)
  50.     {
  51.         grown[i] = 0;
  52.         done [i] = false;
  53.                 if(isConnected(s, i))
  54.                 {
  55.                   prior D1(s, i, _A[s-1][i-1]);
  56.                   Q.Put(D1);
  57.                   explored[i] = _A[s-1][i-1];
  58.                 }
  59.                 else
  60.                   explored[i] = 0;
  61.     }
  62.    
  63.     grown   [1] = s;
  64.     explored[s] = 1;
  65.     done    [s] = true;

  66.     int t = 2;
  67.         /** Unless the queue is empty */
  68.     while (!Q.isEmpty()) {
  69.         
  70.         prior e = Q.Get();
  71.                 /** Pop the vertex from the queue */
  72.         grown[t] = e.val;

  73.                 /** display the explored vertices */
  74.         std::cout << e.fval << "-" << e.val << " ";
  75.         done[grown[t]] = true;

  76.         /** From the explored vertex v try to explore all the
  77.         connected vertices */
  78.         for (int w = 1; w <= _n; ++w)

  79.             /** Explores the vertex w if it is connected to v */
  80.             if (isConnected(grown[t], w)) {
  81.                 if(!explored[w])
  82.                 {
  83.                         prior D2(grown[t], w, _A[grown[t]-1][w-1]);
  84.                                         /** adds the vertex w to the queue */
  85.                         Q.Put(D2);
  86.                         /** marks the vertex w as visited */
  87.                         explored[w] = _A[grown[t]-1][w-1];
  88.                 }
  89.                                 else
  90.                                 {
  91.                                         if(!done[w] && _A[grown[t]-1][w-1] < explored[w])
  92.                                         {
  93.                                                 prior D3(grown[t], w, _A[grown[t]-1][w-1]);
  94.                                                 Q.Push(D3);
  95.                                                 explored[w] = _A[grown[t]-1][w-1];
  96.                                         }
  97.                                 }
  98.             }
  99.         t++;
  100.     }
  101.     std::cout << std::endl;
  102.     delete [] explored;
  103.     delete [] grown;
  104.     delete [] done;
  105. }

  106. void Graph::Kruskal(int s) {
  107.         Queue Q;
  108.         DisjointSet UF(_n);
  109.         for (int i=1; i<_n; ++i)
  110.         {
  111.                 for(int j=i+1; j<_n; ++j)
  112.                 if(isConnected(i, j))
  113.                 {
  114.                   prior D1(i, j, _A[i-1][j-1]);
  115.                   Q.Put(D1);
  116.                 }
  117.         }
  118.         
  119.         while (!Q.isEmpty() && UF.Count() != 1) {
  120.                 prior e = Q.Get();
  121.                 int v = e.fval; int w = e.val;
  122.                 if(UF.Find(v, w)) continue;
  123.                 UF.Unite(v, w);
  124.                 std::cout << v << "-" << w << " ";
  125.         }
  126. }
复制代码
List.h
  1. #if !defined (LIST_H)
  2. #define LIST_H

  3. class prior{
  4. public:
  5.         prior(int u, int v, int p)
  6.          :fval(u), val(v), priority(p)
  7.         {}
  8.         int        fval;
  9.         int        val;
  10.         const int  priority;
  11. };

  12. class DLink
  13. {
  14. public:
  15.         DLink (prior id)
  16.                 : _id (id)
  17.         {
  18.                 _pPrev = this;
  19.                 _pNext = this;
  20.         }
  21.         DLink *  Prev () const { return _pPrev; }
  22.         DLink *  Next () const { return _pNext; }
  23.         void    SetPrev (DLink* pPrev) { _pPrev = pPrev; }
  24.         void    SetNext (DLink* pNext) { _pNext = pNext; }
  25.         prior   Id () const { return _id; }
  26.         void    Unlink();
  27. private:
  28.         DLink *  _pPrev;
  29.         DLink *  _pNext;
  30.         prior     _id;
  31. };

  32. class Queue
  33. {
  34. public:
  35.         Queue (): _pHead (0) {}
  36.         ~Queue ();
  37.         void    Put ( prior id );
  38.         void    Push ( prior id );
  39.         prior   Get ();
  40.         bool    isEmpty () { return _pHead == 0; }
  41.         DLink * GetHead () const { return _pHead; }
  42. protected:
  43.         DLink*  _pHead;
  44. };

  45. #endif
复制代码
list.cc
  1. #include "list.h"
  2. #include <iostream>
  3. #include <cassert>

  4. void DLink::Unlink()
  5. {
  6.   assert (_pNext != 0);
  7.   assert (_pPrev != 0);
  8.   _pNext->SetPrev (_pPrev);
  9.   _pPrev->SetNext (_pNext);
  10.   _pPrev = this;
  11.   _pNext = this;
  12. }

  13. void Queue::Put (prior id)
  14. {
  15.   DLink * pLink = new DLink (id);
  16.   if (_pHead == 0)
  17.     _pHead = pLink;
  18.   else if(_pHead->Next () == _pHead)
  19.   {
  20.         pLink->SetNext (_pHead);
  21.     pLink->SetPrev (_pHead->Prev ());
  22.     _pHead->SetNext (pLink);
  23.     _pHead->SetPrev (pLink);
  24.     if(id.priority >= _pHead->Id().priority)
  25.       _pHead = pLink;
  26.   }
  27.   else
  28.   {
  29.           DLink * tLink;
  30.           for (tLink = GetHead();
  31.          id.priority < tLink->Id().priority;
  32.          tLink = tLink->Next ())
  33.     {
  34.             if(tLink == _pHead->Prev())
  35.             {
  36.                     if(id.priority < tLink->Id().priority)
  37.                     {
  38.                             pLink->SetNext (_pHead);
  39.                             pLink->SetPrev (_pHead->Prev ());
  40.                             _pHead->Prev ()->SetNext (pLink);
  41.                             _pHead->SetPrev (pLink);
  42.                             return;
  43.                     }
  44.                     break;
  45.             }
  46.     }
  47.     pLink->SetNext (tLink);
  48.     pLink->SetPrev (tLink->Prev ());
  49.     pLink->Prev ()->SetNext (pLink);
  50.     pLink->Next ()->SetPrev (pLink);
  51.     if(tLink == _pHead)
  52.                 _pHead = pLink;
  53.   }
  54. }

  55. void Queue::Push (prior id)
  56. {
  57.   DLink * nLink = new DLink (id);
  58.   if (_pHead == 0)
  59.     _pHead = nLink;
  60.   else if(_pHead->Next () == _pHead)
  61.   {
  62.           if(id.val == _pHead->Id().val)
  63.           {
  64.             _pHead = nLink;
  65.             return;
  66.           }
  67.           else
  68.             Put(id);
  69.   }
  70.   else
  71.   {
  72.           bool flag = false;
  73.           for (DLink * fLink = GetHead();;
  74.              fLink = fLink->Next ())
  75.         {
  76.                 if(fLink == _pHead->Prev())
  77.                 {
  78.                         if(id.val == fLink->Id().val)
  79.                         {
  80.                                 fLink->Unlink();
  81.                                 flag = true;
  82.                         }
  83.                         flag = true;
  84.                 }
  85.                 if(id.val == fLink->Id().val)
  86.                 {
  87.                         if(fLink == _pHead)
  88.                                 _pHead = _pHead->Next();
  89.                         fLink->Unlink();
  90.                         flag = true;
  91.                 }
  92.                 if(flag) break;
  93.         }
  94.         Put(id);
  95.   }
  96. }

  97. prior Queue::Get ()
  98. {
  99.   assert (_pHead != 0);
  100.   DLink * pLink = _pHead->Prev ();
  101.   if (pLink == _pHead) // last one
  102.     _pHead = 0;
  103.   pLink->Unlink ();
  104.   prior result = pLink->Id ();
  105.   delete pLink;
  106.   return result;
  107. }

  108. Queue::~Queue ()
  109. {
  110.   // free the Queue
  111.   while ( _pHead != 0 )
  112.   {
  113.     DLink * pLink = _pHead->Prev ();
  114.     if (pLink == _pHead)
  115.       _pHead = 0;
  116.     pLink->Unlink (); // unlink pLink
  117.     delete pLink;
  118.   }
  119. }
复制代码
DisjointSet.h
  1. #if !defined (DISJOINTSET_H)
  2. #define DISJOINTSET_H

  3. class DisjointSet
  4. {
  5. private:
  6.         int *_id;   // parent link (site indexed)
  7.         int *_sz;   // size of component for roots (site indexed)
  8.         int _count; // number of components
  9.         int _root(int i);
  10. public:
  11.         DisjointSet(int N);
  12.         int Count() { return _count; }
  13.         bool Find(int p,int q);
  14.         void Unite(int p,int q);
  15.         ~DisjointSet(void);
  16. };

  17. #endif
复制代码
DisjointSet.cc
  1. #include "DisjointSet.h"

  2. DisjointSet::DisjointSet(int N)
  3. : _count(N)
  4. {
  5.     _id = new int[N];
  6.     _sz = new int[N];
  7.     for(int i=0; i<N; ++i)
  8.     {
  9.         _id[i] = i;
  10.         _sz[i] = 1;
  11.     }
  12. }

  13. int DisjointSet::_root(int i)
  14. {
  15.     while (i != _id[i])
  16.     {
  17.         _id[i] = _id[_id[i]]; //Path compression.
  18.         i = _id[i];
  19.     }
  20.     return i;
  21. }

  22. bool DisjointSet::Find(int p, int q)
  23. {
  24.     return _root(p) == _root(q);
  25. }

  26. void DisjointSet::Unite(int p, int q)
  27. {
  28.     //Link root of smaller tree to root of larger tree.
  29.     int i = _root(p);
  30.     int j = _root(q);
  31.     if(_sz[i] < _sz[j])
  32.     {
  33.         _id[i] = j; _sz[j] += _sz[i];
  34.     }
  35.     else
  36.     {
  37.         _id[j] = i; _sz[i] += _sz[j];
  38.     }
  39.     _count--;
  40. }

  41. DisjointSet::~DisjointSet(void)
  42. {
  43.     delete [] _id;
  44.     delete [] _sz;
  45. }
复制代码
结果输出
  1. 2-1 2-6 1-3 3-5 5-4 5-7
  2. 1-2 4-5 2-6 1-3 3-5 5-7
复制代码
第二个更新版本见4楼。改良了代码,还增加了Dijkstra最短路径算法。第三个更新版本见5楼,修改了代码以适应vc6.0,增加了网络流算法,修改了GenericPQ中null和Comp的实现。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-2-10 20:26:06 | 显示全部楼层
更新了算法,补充了Kruskal算法。 来看看吧
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-2-18 16:06:39 | 显示全部楼层
本帖最后由 andalousie 于 2014-2-18 16:49 编辑

其实大家应该发现我的山寨优先队列把复杂度直接拖到O(n^2)了吧。。。
可以看看这个,虽然只把顶点的遍历顺序输出出来了,但是这回的优先队列可是O(logn)的,这个代码段用了新的优先队列。
  1. void Graph::Prim(int s) {
  2.     PriorityQueue Q(24);

  3.     /** Keeps track of explored vertices */
  4.     int  *explored = new int [_n+1];
  5.     int  *grown    = new int [_n+1];

  6.     /** Initailized all vertices */
  7.     for (int i = 1; i <= _n; ++i)
  8.     {
  9.         grown[i] = 0;
  10.                 if(isConnected(s, i))
  11.                 {
  12.                   Q.insert(i, _A[s-1][i-1]);
  13.                   explored[i] = _A[s-1][i-1];
  14.                 }
  15.                 else
  16.                   explored[i] = 0;
  17.     }
  18.    
  19.     grown   [1] = s;
  20.     explored[s] = 1;
  21.     std::cout << grown[1] << " ";

  22.     int t = 2;
  23.         /** Unless the queue is empty */
  24.     while (!Q.isEmpty()) {
  25.         
  26.         /** Pop the vertex from the queue */
  27.         grown[t] = Q.pop();

  28.                 /** display the explored vertices */
  29.         std::cout << grown[t] << " ";

  30.         /** From the explored vertex v try to explore all the
  31.         connected vertices */
  32.         for (int w = 1; w <= _n; ++w)

  33.             /** Explores the vertex w if it is connected to v */
  34.             if (isConnected(grown[t], w)) {
  35.                 if(!explored[w])
  36.                 {
  37.                                         /** adds the vertex w to the queue */
  38.                         Q.insert(w, _A[grown[t]-1][w-1]);
  39.                         /** marks the vertex w as visited */
  40.                         explored[w] = _A[grown[t]-1][w-1];
  41.                 }
  42.                                 else
  43.                                 {
  44.                                         if(Q.contains(w) && _A[grown[t]-1][w-1] < explored[w])
  45.                                         {
  46.                                                 Q.change(w, _A[grown[t]-1][w-1]);
  47.                                                 explored[w] = _A[grown[t]-1][w-1];
  48.                                         }
  49.                                 }
  50.             }
  51.         t++;
  52.     }
  53.     std::cout << std::endl;
  54.     delete [] explored;
  55.     delete [] grown;
  56. }
复制代码
优先队列
PQ.h
  1. #if !defined (PQ_H)
  2. #define PQ_H

  3. class PriorityQueue{
  4. private:
  5.         int  _N = 0;
  6.         int  *_pq;
  7.         int  *_index;
  8.         int  *_prior;
  9. public:
  10.         PriorityQueue(int capacity);
  11.         ~PriorityQueue();
  12.         bool  isEmpty() const { return _N == 0; }
  13.         bool  contains(int k) const { return _index[k] != -1; }
  14.         void  insert(int k, int priority);
  15.         void  change(int i, int priority);
  16.         int   pop();
  17. private:
  18.         void swim(int k);
  19.         void sink(int k);
  20.         bool comp(int i, int j) { return _prior[_pq[i]] > _prior[_pq[j]]; }
  21.         void swap(int i, int j)
  22.         {
  23.                 int ex = _pq[i];
  24.                 _pq[i] = _pq[j];
  25.                 _pq[j] = ex;
  26.                 _index[_pq[i]] = i;
  27.                 _index[_pq[j]] = j;
  28.         }
  29. };

  30. PriorityQueue::PriorityQueue(int capacity)
  31. {
  32.         _prior = new int[capacity+1];
  33.         _pq    = new int[capacity+1];
  34.         _index = new int[capacity+1];
  35.         for (int i = 0; i <= capacity; ++i) _index[i] = -1;
  36. }

  37. PriorityQueue::~PriorityQueue(void)
  38. {
  39.         delete [] _pq;
  40.         delete [] _index;
  41.         delete [] _prior;
  42. }

  43. void PriorityQueue::swim(int k)
  44. {
  45.         while (k > 1 && comp(k/2, k))
  46.         {
  47.                 swap(k, k/2);
  48.                 k = k/2;
  49.         }
  50. }

  51. void PriorityQueue::insert(int k, int priority)
  52. {
  53.         _N++;
  54.         _index[k] = _N;
  55.         _pq[_N]   = k;
  56.         _prior[k] = priority;
  57.         swim(_N);
  58. }

  59. void PriorityQueue::change(int i, int priority)
  60. {
  61.         _prior[i] = priority;
  62.         swim(_index[i]);
  63.         sink(_index[i]);
  64. }

  65. void PriorityQueue::sink(int k)
  66. {
  67.         while (2*k <= _N)
  68.         {
  69.                 int j = 2*k;
  70.                 if (j < _N && comp(j, j+1)) j++;
  71.                 if (!comp(k, j)) break;
  72.                 swap(k, j);
  73.                 k = j;
  74.         }
  75. }

  76. int PriorityQueue::pop()
  77. {
  78.         int min = _pq[1];
  79.         swap(1, _N--);
  80.         sink(1);
  81.         _prior[_pq[_N+1]] = 0;
  82.         _index[_pq[_N+1]] = -1;
  83.         return min;
  84. }

  85. #endif
复制代码


小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-2-19 11:51:26 | 显示全部楼层
本帖最后由 andalousie 于 2014-2-19 11:53 编辑

一个更新版本
主测试文件:
MST.cpp
图的头文件和实现文件
graph.h graph.cc
Prim算法的补充文件
PQ.h //用堆实现一个含索引的最小优先队列
Kruskal算法的补充文件
DisjointSet.h DisjointSet.cc //用于实现并查集,文件不变。
GPQ.h //用于实现泛型最小优先队列。
Dijkstra最短路径算法
PQ.h //和Prim算法一样
stack.h, stack.cc //实现栈结构。文件参考我另一篇文章的代码
下面就是需要列出的文件
graph.h
  1. #if !defined (GRAPH_H)
  2. #define GRAPH_H

  3. /************************************************************

  4. Class Graph represents a Graph [V,E] having vertices V and
  5. edges E.

  6. ************************************************************/
  7. class Graph {
  8.     private:
  9.         int    _n;  /// n is the number of vertices in the graph
  10.         int ** _A;  /// A stores the edges between two vertices
  11.     public:
  12.         Graph(int size = 2);
  13.         ~Graph();
  14.         bool isConnected(int, int);
  15.         void addEdge(int x, int y, int d);
  16.         void Prim(int s);
  17.         void Kruskal(int s);
  18.         void Dijkstra(int s, int q);
  19. };

  20. struct Edge{
  21.         Edge() {};
  22.         Edge(int u, int v, int d)
  23.         : fval(u), val(v), weight(d)
  24.         {}
  25.         int fval;
  26.         int val;
  27.         int weight;
  28. };

  29. #endif
复制代码
graph.cc
  1. #include <iostream>
  2. #include "graph.h"
  3. #include "PQ.h"
  4. #include "GPQ.h"
  5. #include "DisjointSet.h"
  6. #include "stack.h"

  7. Graph::Graph(int size) {
  8.     int i, j;
  9.     if (size < 2) _n = 2;
  10.     else _n = size;
  11.     _A = new int*[_n];
  12.     for (i = 0; i < _n; ++i)
  13.         _A[i] = new int[_n];
  14.     for (i = 0; i < _n; ++i)
  15.         for (j = 0; j < _n; ++j)
  16.             _A[i][j] = 0;
  17. }

  18. Graph::~Graph() {
  19.     for (int i = 0; i < _n; ++i)
  20.     delete [] _A[i];
  21.     delete [] _A;
  22. }

  23. /******************************************************
  24. Checks if two given vertices are connected by an edge
  25. @param u vertex
  26. @param v vertex
  27. @return true if connected false if not connected
  28. ******************************************************/
  29. bool Graph::isConnected(int x, int y) {
  30.     return (_A[x-1][y-1] != 0);
  31. }

  32. /*****************************************************
  33. adds an edge E to the graph G.
  34. @param u vertex
  35. @param v vertex
  36. *****************************************************/
  37. void Graph::addEdge(int x, int y, int d) {
  38.     _A[x-1][y-1] = d; _A[y-1][x-1] = d;
  39. }

  40. /*****************************************************
  41. performs Prim's algorithm
  42. @param s initial vertex
  43. *****************************************************/
  44. void Graph::Prim(int s) {
  45.     PriorityQueue Q(24);

  46.     /** Keeps track of explored vertices */
  47.     int  *explored = new int [_n+1];
  48.     int  *grown    = new int [_n+1];
  49.     int  *prev     = new int [_n+1];

  50.     /** Initailized all vertices */
  51.     for (int i = 1; i <= _n; ++i)
  52.     {
  53.         grown[i] = 0;
  54.                 if(isConnected(s, i))
  55.                 {
  56.                   Q.insert(i, _A[s-1][i-1]);
  57.                   explored[i] = _A[s-1][i-1];
  58.                   prev    [i] = s;
  59.                 }
  60.                 else
  61.                 {
  62.                   explored[i] = 0;
  63.                   prev    [i] = 0;
  64.                 }
  65.     }
  66.    
  67.     grown   [1] = s;
  68.     explored[s] = 1;

  69.     int t = 2;
  70.         /** Unless the queue is empty */
  71.     while (!Q.isEmpty()) {
  72.         
  73.         /** Pop the vertex from the queue */
  74.         grown[t] = Q.pop();

  75.                 /** display the explored vertices */
  76.         std::cout << prev[grown[t]] << "-" << grown[t] << " ";

  77.         /** From the explored vertex v try to explore all the
  78.         connected vertices */
  79.         for (int w = 1; w <= _n; ++w)

  80.             /** Explores the vertex w if it is connected to v */
  81.             if (isConnected(grown[t], w)) {
  82.                 if(!explored[w])
  83.                 {
  84.                                         /** adds the vertex w to the queue */
  85.                         Q.insert(w, _A[grown[t]-1][w-1]);
  86.                         /** marks the vertex w as visited */
  87.                         explored[w] = _A[grown[t]-1][w-1];
  88.                         prev    [w] = grown[t];
  89.                 }
  90.                                 else
  91.                                 {
  92.                                         if(Q.contains(w) && _A[grown[t]-1][w-1] < explored[w])
  93.                                         {
  94.                                                 Q.change(w, _A[grown[t]-1][w-1]);
  95.                                                 explored[w] = _A[grown[t]-1][w-1];
  96.                                                 prev    [w] = grown[t];
  97.                                         }
  98.                                 }
  99.             }
  100.         t++;
  101.     }
  102.     std::cout << std::endl;
  103.     delete [] explored;
  104.     delete [] grown;
  105.     delete [] prev;
  106. }

  107. /*****************************************************
  108. performs Kruskal's algorithm
  109. @param s initial vertex
  110. *****************************************************/
  111. void Graph::Kruskal(int s) {
  112.         GenericPQ<Edge> Q(16);
  113.         DisjointSet UF(_n);
  114.         for (int i=1; i<_n; ++i)
  115.         {
  116.                 for(int j=i+1; j<_n; ++j)
  117.                 if(isConnected(i, j))
  118.                 {
  119.                   Edge e(i, j, _A[i-1][j-1]);
  120.                   Q.insert(e);
  121.                 }
  122.         }
  123.         
  124.         while (!Q.isEmpty() && UF.Count() != 1) {
  125.                 Edge e = Q.pop();
  126.                 int  v = e.fval;
  127.                 int  w = e.val;
  128.                 if(UF.Find(v, w)) continue;
  129.                 UF.Unite(v, w);
  130.                 std::cout << v << "-" << w << " ";
  131.         }
  132.         std::cout << std::endl;
  133. }

  134. /*****************************************************
  135. performs Dijkstra's algorithm
  136. @param s initial vertex
  137. *****************************************************/
  138. void Graph::Dijkstra(int s, int q) {
  139.     PriorityQueue Q(16);
  140.     IStack stack;

  141.     /** Keeps track of explored vertices */
  142.     int  *explored = new int [_n+1];
  143.     int  *grown    = new int [_n+1];
  144.     int  *prev     = new int [_n+1];

  145.     /** Initailized all vertices */
  146.     for (int i = 1; i <= _n; ++i)
  147.     {
  148.         grown[i] = 0;
  149.                 if(isConnected(s, i))
  150.                 {
  151.                   Q.insert(i, _A[s-1][i-1]);
  152.                   explored[i] = _A[s-1][i-1];
  153.                   prev    [i] = s;
  154.                 }
  155.                 else
  156.                 {
  157.                   explored[i] = 0;
  158.                   prev    [i] = 0;
  159.                 }
  160.     }
  161.    
  162.     grown   [1] = s;
  163.     explored[s] = 1;

  164.     int t = 2;
  165.         /** Unless the queue is empty */
  166.     while (!Q.isEmpty()) {
  167.         
  168.         /** Pop the vertex from the queue */
  169.         grown[t] = Q.pop();

  170.         /** From the explored vertex v try to explore all the
  171.         connected vertices */
  172.         for (int w = 1; w <= _n; ++w)

  173.             /** Explores the vertex w if it is connected to v */
  174.             if (isConnected(grown[t], w)) {
  175.                 if(!explored[w])
  176.                 {
  177.                                         /** adds the vertex w to the queue */
  178.                         Q.insert(w, explored[t] + _A[grown[t]-1][w-1]);
  179.                         /** marks the vertex w as visited */
  180.                         explored[w] = explored[t] + _A[grown[t]-1][w-1];
  181.                         prev    [w] = grown[t];
  182.                 }
  183.                                 else
  184.                                 {
  185.                                         if(Q.contains(w) && explored[t] + _A[grown[t]-1][w-1] < explored[w])
  186.                                         {
  187.                                                 Q.change(w, explored[t] + _A[grown[t]-1][w-1]);
  188.                                                 explored[w] = explored[t] + _A[grown[t]-1][w-1];
  189.                                                 prev    [w] = grown[t];
  190.                                         }
  191.                                 }
  192.             }
  193.         t++;
  194.     }
  195.    
  196.     t = q;
  197.     while(prev[t])
  198.     {
  199.             stack.push(t);
  200.                 t = prev[t];
  201.     }
  202.    
  203.     std::cout << s;
  204.     while(!stack.isEmpty())
  205.     {
  206.             std::cout << "-" << stack.pop();
  207.     }
  208.     std::cout << std::endl;
  209.    
  210.     delete [] explored;
  211.     delete [] grown;
  212.     delete [] prev;
  213. }
复制代码
PQ.h
  1. #if !defined (PQ_H)
  2. #define PQ_H

  3. class PriorityQueue{
  4. private:
  5.         int  _N = 0;
  6.         int  *_pq;
  7.         int  *_index;
  8.         int  *_prior;
  9. public:
  10.         PriorityQueue(int capacity);
  11.         ~PriorityQueue();
  12.         bool  isEmpty() const { return _N == 0; }
  13.         bool  contains(int k) const { return _index[k] != -1; }
  14.         void  insert(int k, int priority);
  15.         void  change(int i, int priority);
  16.         int   pop();
  17. private:
  18.         void swim(int k);
  19.         void sink(int k);
  20.         bool comp(int i, int j) { return _prior[_pq[i]] > _prior[_pq[j]]; }
  21.         void swap(int i, int j)
  22.         {
  23.                 int ex = _pq[i];
  24.                 _pq[i] = _pq[j];
  25.                 _pq[j] = ex;
  26.                 _index[_pq[i]] = i;
  27.                 _index[_pq[j]] = j;
  28.         }
  29. };

  30. PriorityQueue::PriorityQueue(int capacity)
  31. {
  32.         _prior = new int[capacity+1];
  33.         _pq    = new int[capacity+1];
  34.         _index = new int[capacity+1];
  35.         for (int i = 0; i <= capacity; ++i) _index[i] = -1;
  36. }

  37. PriorityQueue::~PriorityQueue(void)
  38. {
  39.         delete [] _pq;
  40.         delete [] _index;
  41.         delete [] _prior;
  42. }

  43. void PriorityQueue::swim(int k)
  44. {
  45.         while (k > 1 && comp(k/2, k))
  46.         {
  47.                 swap(k, k/2);
  48.                 k = k/2;
  49.         }
  50. }

  51. void PriorityQueue::insert(int k, int priority)
  52. {
  53.         _N++;
  54.         _index[k] = _N;
  55.         _pq[_N]   = k;
  56.         _prior[k] = priority;
  57.         swim(_N);
  58. }

  59. void PriorityQueue::change(int i, int priority)
  60. {
  61.         _prior[i] = priority;
  62.         swim(_index[i]);
  63.         sink(_index[i]);
  64. }

  65. void PriorityQueue::sink(int k)
  66. {
  67.         while (2*k <= _N)
  68.         {
  69.                 int j = 2*k;
  70.                 if (j < _N && comp(j, j+1)) j++;
  71.                 if (!comp(k, j)) break;
  72.                 swap(k, j);
  73.                 k = j;
  74.         }
  75. }

  76. int PriorityQueue::pop()
  77. {
  78.         int min = _pq[1];
  79.         swap(1, _N--);
  80.         sink(1);
  81.         _prior[_pq[_N+1]] = 0;
  82.         _index[_pq[_N+1]] = -1;
  83.         return min;
  84. }

  85. #endif
复制代码
GPQ.h
  1. #if !defined (GPQ_H)
  2. #define GPQ_H

  3. struct Edge nulledge;

  4. template<class T>
  5. class GenericPQ{
  6. private:
  7.         T    *_pq;               // heap-ordered complete binary tree
  8.         int  _N = 0;             // in pq[1..N] with pq[0] unused
  9. public:
  10.         GenericPQ(int capacity);
  11.         ~GenericPQ();
  12.         bool isEmpty() { return _N == 0; }
  13.         void insert(T x);
  14.         T    pop();
  15. private:
  16.         void swim(int k);
  17.         void sink(int k);
  18.         //Compare and exchange methods for heap implementations
  19.         bool comp(int i, int j) { return _pq[i].weight > _pq[j].weight; }
  20.         void swap(int i, int j)
  21.         {
  22.                 T ex   = _pq[i];
  23.                 _pq[i] = _pq[j];
  24.                 _pq[j] = ex;
  25.         }
  26. };

  27. template<class T>
  28. GenericPQ<T>::GenericPQ(int capacity)
  29. {
  30.         _pq = new T[capacity+1];
  31. }

  32. template<class T>
  33. GenericPQ<T>::~GenericPQ(void)
  34. {
  35.         delete [] _pq;
  36. }

  37. /** Bottom-up reheapify (swim) implementation */
  38. template<class T>
  39. void GenericPQ<T>::swim(int k)
  40. {
  41.         while (k > 1 && comp(k/2, k))
  42.         {
  43.                 swap(k, k/2);
  44.                 k = k/2;
  45.         }
  46. }

  47. template<class T>
  48. void GenericPQ<T>::insert(T x)
  49. {
  50.         _pq[++_N] = x;
  51.         swim(_N);
  52. }

  53. /** Top-down reheapify (sink) implementation **/
  54. template<class T>
  55. void GenericPQ<T>::sink(int k)
  56. {
  57.         while (2*k <= _N)
  58.         {
  59.                 int j = 2*k;
  60.                 if (j < _N && comp(j, j+1)) j++;
  61.                 if (!comp(k, j)) break;
  62.                 swap(k, j);
  63.                 k = j;
  64.         }
  65. }

  66. template<class T>
  67. T GenericPQ<T>::pop()
  68. {
  69.         T min = _pq[1];          // Retrieve max key from top.
  70.         swap(1, _N--);           // Exchange with last item.
  71.         sink(1);                 // Avoid loitering.
  72.         _pq[_N+1] = nulledge;    // Restore heap property.
  73.         return min;
  74. }

  75. #endif
复制代码
MST.h
  1. #include <iostream>
  2. #include "graph.h"

  3. int main(){
  4.         /** Creates a graph with 12 vertices */
  5.     Graph g1(10);

  6.     /** Adds edges to the graph */
  7.     g1.addEdge(1, 2, 5); g1.addEdge(1, 3, 7);
  8.     g1.addEdge(2, 3, 9); g1.addEdge(2, 6, 6);
  9.     g1.addEdge(2, 5, 15); g1.addEdge(3, 4, 8);
  10.     g1.addEdge(3, 5, 7); g1.addEdge(4, 5, 5);
  11.     g1.addEdge(5, 6, 8); g1.addEdge(5, 7, 9);
  12.     g1.addEdge(6, 7, 11);

  13.     /** Explores all vertices findable from vertex 1 */
  14.     g1.Prim(2);
  15.     g1.Kruskal(2);
  16.     g1.Dijkstra(1, 6);
  17. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-16 00:10:30 | 显示全部楼层
第三个版本
为了在vc6.0上面能够支持,稍做了修改。增加了最大流算法,但没有验证是否正确。
graph.h
  1. #if !defined (GRAPH_H)
  2. #define GRAPH_H

  3. /************************************************************

  4. Class Graph represents a Graph [V,E] having vertices V and
  5. edges E.

  6. ************************************************************/
  7. class Graph {
  8.     private:
  9.         int    _n;  /// n is the number of vertices in the graph
  10.         int ** _A;  /// A stores the edges between two vertices
  11.     public:
  12.         Graph(int size = 2);
  13.         ~Graph();
  14.         bool isConnected(int, int);
  15.         void addEdge(int x, int y, int d);
  16.         void Prim(int s);
  17.         void Kruskal(int s);
  18.         void Dijkstra(int s, int q);
  19.                 bool BFS(int **residual, int s, int required, int *parent);
  20.                 int  Maxflow(int s, int q);
  21. };

  22. struct Edge{
  23.         Edge() {}
  24.         Edge(int null) {}
  25.         Edge(int u, int v, int d)
  26.         : fval(u), val(v), weight(d)
  27.         {}
  28.         bool operator > (Edge& other)
  29.         {
  30.                 return weight > other.weight;
  31.         }
  32.         int fval;
  33.         int val;
  34.         int weight;
  35. };

  36. #endif
复制代码
queue.h和queue.cpp参见http://bbs.fishc.com/thread-43422-1-1.html
GPQ.h
  1. #if !defined (GPQ_H)
  2. #define GPQ_H

  3. template<class T>
  4. class GenericPQ{
  5. private:
  6.         T    *_pq;               // heap-ordered complete binary tree
  7.         T    _null;
  8.         int  _N;             // in pq[1..N] with pq[0] unused
  9. public:
  10.         GenericPQ(int capacity);
  11.         ~GenericPQ();
  12.         bool isEmpty() { return _N == 0; }
  13.         void insert(T x);
  14.         T    pop();
  15. private:
  16.         void swim(int k);
  17.         void sink(int k);
  18.         //Compare and exchange methods for heap implementations
  19.         bool comp(int i, int j) { return _pq[i] > _pq[j]; }
  20.         void swap(int i, int j)
  21.         {
  22.                 T ex   = _pq[i];
  23.                 _pq[i] = _pq[j];
  24.                 _pq[j] = ex;
  25.         }
  26. };

  27. template<class T>
  28. GenericPQ<T>::GenericPQ(int capacity)
  29. :_N(0), _null(0)
  30. {
  31.         _pq = new T[capacity+1];
  32. }

  33. template<class T>
  34. GenericPQ<T>::~GenericPQ(void)
  35. {
  36.         delete [] _pq;
  37. }

  38. /** Bottom-up reheapify (swim) implementation */
  39. template<class T>
  40. void GenericPQ<T>::swim(int k)
  41. {
  42.         while (k > 1 && comp(k/2, k))
  43.         {
  44.                 swap(k, k/2);
  45.                 k = k/2;
  46.         }
  47. }

  48. template<class T>
  49. void GenericPQ<T>::insert(T x)
  50. {
  51.         _pq[++_N] = x;
  52.         swim(_N);
  53. }

  54. /** Top-down reheapify (sink) implementation **/
  55. template<class T>
  56. void GenericPQ<T>::sink(int k)
  57. {
  58.         while (2*k <= _N)
  59.         {
  60.                 int j = 2*k;
  61.                 if (j < _N && comp(j, j+1)) j++;
  62.                 if (!comp(k, j)) break;
  63.                 swap(k, j);
  64.                 k = j;
  65.         }
  66. }

  67. template<class T>
  68. T GenericPQ<T>::pop()
  69. {
  70.         T min = _pq[1];          // Retrieve max key from top.
  71.         swap(1, _N--);           // Exchange with last item.
  72.         sink(1);                 // Avoid loitering.
  73.         _pq[_N+1] = _null;    // Restore heap property.
  74.         return min;
  75. }

  76. #endif
复制代码
graph.cc
  1. #include <iostream>
  2. #include "graph.h"
  3. #include "queue.h"
  4. #include "PQ.h"
  5. #include "GPQ.h"
  6. #include "DisjointSet.h"
  7. #include "stack.h"

  8. Graph::Graph(int size) {
  9.     int i, j;
  10.     if (size < 2) _n = 2;
  11.     else _n = size;
  12.     _A = new int*[_n];
  13.     for (i = 0; i < _n; ++i)
  14.         _A[i] = new int[_n];
  15.     for (i = 0; i < _n; ++i)
  16.         for (j = 0; j < _n; ++j)
  17.             _A[i][j] = 0;
  18. }

  19. Graph::~Graph() {
  20.     for (int i = 0; i < _n; ++i)
  21.     delete [] _A[i];
  22.     delete [] _A;
  23. }

  24. /******************************************************
  25. Checks if two given vertices are connected by an edge
  26. @param u vertex
  27. @param v vertex
  28. @return true if connected false if not connected
  29. ******************************************************/
  30. bool Graph::isConnected(int x, int y) {
  31.     return (_A[x-1][y-1] != 0);
  32. }

  33. /*****************************************************
  34. adds an edge E to the graph G.
  35. @param u vertex
  36. @param v vertex
  37. *****************************************************/
  38. void Graph::addEdge(int x, int y, int d) {
  39.     _A[x-1][y-1] = d; _A[y-1][x-1] = d;
  40. }

  41. /*****************************************************
  42. performs Prim's algorithm
  43. @param s initial vertex
  44. *****************************************************/
  45. void Graph::Prim(int s) {
  46.     PriorityQueue Q(24);

  47.     /** Keeps track of explored vertices */
  48.     int  *explored = new int [_n+1];
  49.     int  *grown    = new int [_n+1];
  50.     int  *prev     = new int [_n+1];

  51.     /** Initailized all vertices */
  52.     for (int i = 1; i <= _n; ++i)
  53.     {
  54.         grown[i] = 0;
  55.                 if(isConnected(s, i))
  56.                 {
  57.                   Q.insert(i, _A[s-1][i-1]);
  58.                   explored[i] = _A[s-1][i-1];
  59.                   prev    [i] = s;
  60.                 }
  61.                 else
  62.                 {
  63.                   explored[i] = 0;
  64.                   prev    [i] = 0;
  65.                 }
  66.     }
  67.    
  68.     grown   [1] = s;
  69.     explored[s] = 1;

  70.     int t = 2;
  71.         /** Unless the queue is empty */
  72.     while (!Q.isEmpty()) {
  73.         
  74.         /** Pop the vertex from the queue */
  75.         grown[t] = Q.pop();

  76.                 /** display the explored vertices */
  77.         std::cout << prev[grown[t]] << "-" << grown[t] << " ";

  78.         /** From the explored vertex v try to explore all the
  79.         connected vertices */
  80.         for (int w = 1; w <= _n; ++w)

  81.             /** Explores the vertex w if it is connected to v */
  82.             if (isConnected(grown[t], w)) {
  83.                 if(!explored[w])
  84.                 {
  85.                                         /** adds the vertex w to the queue */
  86.                         Q.insert(w, _A[grown[t]-1][w-1]);
  87.                         /** marks the vertex w as visited */
  88.                         explored[w] = _A[grown[t]-1][w-1];
  89.                         prev    [w] = grown[t];
  90.                 }
  91.                                 else
  92.                                 {
  93.                                         if(Q.contains(w) && _A[grown[t]-1][w-1] < explored[w])
  94.                                         {
  95.                                                 Q.change(w, _A[grown[t]-1][w-1]);
  96.                                                 explored[w] = _A[grown[t]-1][w-1];
  97.                                                 prev    [w] = grown[t];
  98.                                         }
  99.                                 }
  100.             }
  101.         t++;
  102.     }
  103.     std::cout << std::endl;
  104.     delete [] explored;
  105.     delete [] grown;
  106.     delete [] prev;
  107. }

  108. /*****************************************************
  109. performs Kruskal's algorithm
  110. @param s initial vertex
  111. *****************************************************/
  112. void Graph::Kruskal(int s) {
  113.         GenericPQ<Edge> Q(16);
  114.         DisjointSet UF(_n);
  115.         for (int i=1; i<_n; ++i)
  116.         {
  117.                 for(int j=i+1; j<_n; ++j)
  118.                 if(isConnected(i, j))
  119.                 {
  120.                   Edge e(i, j, _A[i-1][j-1]);
  121.                   Q.insert(e);
  122.                 }
  123.         }
  124.        
  125.         while (!Q.isEmpty() && UF.Count() != 1) {
  126.                 Edge e = Q.pop();
  127.                 int  v = e.fval;
  128.                 int  w = e.val;
  129.                 if(UF.Find(v, w)) continue;
  130.                 UF.Unite(v, w);
  131.                 std::cout << v << "-" << w << " ";
  132.         }
  133.         std::cout << std::endl;
  134. }

  135. /*****************************************************
  136. performs Dijkstra's algorithm
  137. @param s initial vertex
  138. *****************************************************/
  139. void Graph::Dijkstra(int s, int q) {
  140.     PriorityQueue Q(16);
  141.     IStack stack;

  142.     /** Keeps track of explored vertices */
  143.     int  *explored = new int [_n+1];
  144.     int  *grown    = new int [_n+1];
  145.     int  *prev     = new int [_n+1];

  146.     /** Initailized all vertices */
  147.     for (int i = 1; i <= _n; ++i)
  148.     {
  149.         grown[i] = 0;
  150.                 if(isConnected(s, i))
  151.                 {
  152.                   Q.insert(i, _A[s-1][i-1]);
  153.                   explored[i] = _A[s-1][i-1];
  154.                   prev    [i] = s;
  155.                 }
  156.                 else
  157.                 {
  158.                   explored[i] = 0;
  159.                   prev    [i] = 0;
  160.                 }
  161.     }
  162.    
  163.     grown   [1] = s;
  164.     explored[s] = 1;

  165.     int t = 2;
  166.         /** Unless the queue is empty */
  167.     while (!Q.isEmpty()) {
  168.         
  169.         /** Pop the vertex from the queue */
  170.         grown[t] = Q.pop();

  171.         /** From the explored vertex v try to explore all the
  172.         connected vertices */
  173.         for (int w = 1; w <= _n; ++w)

  174.             /** Explores the vertex w if it is connected to v */
  175.             if (isConnected(grown[t], w)) {
  176.                 if(!explored[w])
  177.                 {
  178.                                         /** adds the vertex w to the queue */
  179.                         Q.insert(w, explored[t] + _A[grown[t]-1][w-1]);
  180.                         /** marks the vertex w as visited */
  181.                         explored[w] = explored[t] + _A[grown[t]-1][w-1];
  182.                         prev    [w] = grown[t];
  183.                 }
  184.                                 else
  185.                                 {
  186.                                         if(Q.contains(w) && explored[t] + _A[grown[t]-1][w-1] < explored[w])
  187.                                         {
  188.                                                 Q.change(w, explored[t] + _A[grown[t]-1][w-1]);
  189.                                                 explored[w] = explored[t] + _A[grown[t]-1][w-1];
  190.                                                 prev    [w] = grown[t];
  191.                                         }
  192.                                 }
  193.             }
  194.         t++;
  195.     }
  196.    
  197.     t = q;
  198.     while(prev[t])
  199.     {
  200.             stack.push(t);
  201.                 t = prev[t];
  202.     }
  203.    
  204.     std::cout << s;
  205.     while(!stack.isEmpty())
  206.     {
  207.             std::cout << "-" << stack.pop();
  208.     }
  209.     std::cout << std::endl;
  210.    
  211.     delete [] explored;
  212.     delete [] grown;
  213.     delete [] prev;
  214. }

  215. /*****************************************************
  216. performs Breadth First Search
  217. @param s initial vertex
  218. *****************************************************/
  219. bool Graph::BFS(int **residual, int s, int required, int *parent) {
  220.     Queue Q;

  221.     /** Keeps track of explored vertices */
  222.     bool *explored = new bool[_n+1];

  223.     /** Initailized all vertices as unexplored */
  224.     for (int i = 1; i <= _n; ++i)
  225.         explored[i] = false;

  226.     /** Push initial vertex to the queue */
  227.     Q.enqueue(s);
  228.     explored[s] = true; /** mark it as explored */
  229.         parent[s] = -1;

  230.     /** Unless the queue is empty */
  231.     while (!Q.isEmpty()) {
  232.         /** Pop the vertex from the queue */
  233.         int v = Q.dequeue();

  234.         if(v == required)
  235.                 {
  236.                         delete [] explored;
  237.                         return true;
  238.                 }

  239.         /** From the explored vertex v try to explore all the
  240.         connected vertices */
  241.         for (int w = 1; w <= _n; ++w)

  242.             /** Explores the vertex w if it is connected to v
  243.             and and if it is unexplored */
  244.             if (residual[v-1][w-1] && !explored[w]) {
  245.                 /** adds the vertex w to the queue */
  246.                 Q.enqueue(w);
  247.                                 parent[w] = v;
  248.                 /** marks the vertex w as visited */
  249.                 explored[w] = true;
  250.             }
  251.     }
  252.     delete [] explored;
  253.         return false;
  254. }

  255. /*****************************************************
  256. performs Edmonds–Karp algorithm
  257. @param s initial vertex
  258. *****************************************************/
  259. int Graph::Maxflow(int s, int q)
  260. {
  261.     // Create a residual graph and fill the residual graph with
  262.     // given capacities in the original graph as residual capacities
  263.     // in residual graph
  264.     int **residual = new int*[_n];
  265.     for (int i = 0; i < _n; ++i)
  266.         residual[i] = new int[_n];
  267.                      // Residual graph where residual[i][j] indicates
  268.                      // residual capacity of edge from i to j (if there
  269.                      // is an edge. If residual[i][j] is 0, then there is not)  
  270.     for (int u = 0; u < _n; u++)
  271.         for (int w = 0; w < _n; w++)
  272.              residual[u][w] = _A[u][w];

  273.     int *parent = new int [_n+1];  // This queue is filled by BFS and to store path

  274.     int max_flow = 0;  // There is no flow initially

  275.     // Augment the flow while tere is path from source to sink
  276.         int v = 0;
  277.     while (BFS(residual, s, q, parent))
  278.     {
  279.         // Find minimum residual capacity of the edhes along the
  280.         // path filled by BFS. Or we can say find the maximum flow
  281.         // through the path found.
  282.                 GenericPQ<int> cf(25);
  283.         for (v = q; v != s; v = parent[v])
  284.         {
  285.             u = parent[v];
  286.             cf.insert(residual[u-1][v-1]);
  287.         }
  288.                 int path_flow = cf.pop();

  289.         // update residual capacities of the edges and reverse edges
  290.         // along the path
  291.         for (v = q; v != s; v = parent[v])
  292.         {
  293.             u = parent[v];
  294.             residual[u-1][v-1] -= path_flow;
  295.             residual[v-1][u-1] += path_flow;
  296.         }

  297.         // Add path flow to overall flow
  298.         max_flow += path_flow;
  299.     }

  300.         for (int j = 0; j < _n; ++j)
  301.     delete [] residual[j];
  302.         delete [] residual;
  303.         delete [] parent;
  304.     // Return the overall flow
  305.     return max_flow;
  306. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-16 01:50:07 | 显示全部楼层
看一看 看一看
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-16 08:41:12 | 显示全部楼层
看看。。。。。。。了解
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-16 09:43:03 | 显示全部楼层
感谢楼主分享,不错学习学习!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-3-16 11:53:23 | 显示全部楼层
看看学习一下 ........
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-18 02:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表