日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ AOE网络

發布時間:2023/12/16 c/c++ 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ AOE网络 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、思路(你可以用拓撲排序來做,但我這里沒用拓撲排序)

??? (1)求事件Vi的最早可能開始時間是從源點V0到頂點Vi的最長路徑長度。

???????????? 如V0=0, V1=6,V2=4,V3=5;V4事件要等V1和V2事件完成后才可以進行,所以要取事件用的最長的時間,即V4=6+1=7,同樣道理得出其他時間。

??? (2)事件Vi的最遲允許開始時間Vl[i]是在保證匯點Vn-1在Ve[n-1]時刻完成的前提下,事件Vi的允許的最遲開始時間。它等于Ve[n-1]減去從Vi到Vn-1的最長路徑。

???????? 如:事件V2=Ve[n-1]-(a7+a10)-a5 = 18-11-1=6

??? (3)活動ak的最早可能開始時間Ae[k]=Ve[i](k=1,2,…)(i=0,1,…)

??? (4)活動ak的最遲允許開始時間Al[k]=Vl[j]-<i,j>

??? (5)用Al[k]-Ae[k]表示活動ak的最早可能開始時間和最遲允許開始時間的時間余量,也叫做松弛時間。Al[k]==Ae[k]表示活動ak是沒有時間余量的關鍵活動。

事件

V0

V1

V2

V3

V4

V5

V6

V7

V8

Ve[i]

0

6

4

5

7

7

16

14

18

Vl[i]

0

6

6

Ve[8]-a11-a9-a6=8

7

10

16

14

18

?

<0, 1>

<0, 2>

<0, 3>

<1, 4>

<2, 4>

<3, 5>

<4, 6>

<4, 7>

<5, 7>

<6, 8>

<7, 8>

活動

a1

a2

a3

a4

a5

a6

a7

a8

a9

a10

a11

Ae

Ve[i]=Ve[0]=0

Ve[i]=Ve[0]=0

Ve[i]=Ve[0]=0

Ve[i]=Ve[1]=6

Ve[2]=0

4

5

7

7

7

16

14

Al

Vl[1]-6=6-6=0

Vl[2]-<0,2>=6-4=2

Vl[3]-<0,3>=8-5=3

6

6

8

7

7

10

16

14

Al-Ae

0

2

3

0

2

3

0

0

3

0

0

關鍵活動

?

?

?

?

?

?

?

二、實現程序:

1.Graph.h:有向圖的鏈表表示

#ifndef Graph_h #define Graph_h#include <iostream> using namespace std;const int DefaultVertices = 30;template <class T, class E> struct Edge { // 邊結點的定義int dest; // 邊的另一頂點位置E cost; // 表上的權值Edge<T, E> *link; // 下一條邊鏈指針 };template <class T, class E> struct Vertex { // 頂點的定義T data; // 頂點的名字Edge<T, E> *adj; // 邊鏈表的頭指針 };template <class T, class E> class Graphlnk { public:const E maxValue = 100000; // 代表無窮大的值(=∞)Graphlnk(int sz=DefaultVertices); // 構造函數~Graphlnk(); // 析構函數void inputGraph(); // 建立鄰接表表示的圖void outputGraph(); // 輸出圖中的所有頂點和邊信息T getValue(int i); // 取位置為i的頂點中的值E getWeight(int v1, int v2); // 返回邊(v1, v2)上的權值bool insertVertex(const T& vertex); // 插入頂點bool insertEdge(int v1, int v2, E weight); // 插入邊bool removeVertex(int v); // 刪除頂點bool removeEdge(int v1, int v2); // 刪除邊int getFirstNeighbor(int v); // 取頂點v的第一個鄰接頂點int getNextNeighbor(int v,int w); // 取頂點v的鄰接頂點w的下一鄰接頂點int getVertexPos(const T vertex); // 給出頂點vertex在圖中的位置int numberOfVertices(); // 當前頂點數 private:int maxVertices; // 圖中最大的頂點數int numEdges; // 當前邊數int numVertices; // 當前頂點數Vertex<T, E> * nodeTable; // 頂點表(各邊鏈表的頭結點) };// 構造函數:建立一個空的鄰接表 template <class T, class E> Graphlnk<T, E>::Graphlnk(int sz) {maxVertices = sz;numVertices = 0;numEdges = 0;nodeTable = new Vertex<T, E>[maxVertices]; // 創建頂點表數組if(nodeTable == NULL) {cerr << "存儲空間分配錯誤!" << endl;exit(1);}for(int i = 0; i < maxVertices; i++)nodeTable[i].adj = NULL; }// 析構函數 template <class T, class E> Graphlnk<T, E>::~Graphlnk() {// 刪除各邊鏈表中的結點for(int i = 0; i < numVertices; i++) {Edge<T, E> *p = nodeTable[i].adj; // 找到其對應鏈表的首結點while(p != NULL) { // 不斷地刪除第一個結點nodeTable[i].adj = p->link;delete p;p = nodeTable[i].adj;}}delete []nodeTable; // 刪除頂點表數組 }// 建立鄰接表表示的圖 template <class T, class E> void Graphlnk<T, E>::inputGraph() {int n, m; // 存儲頂點樹和邊數int i, j, k;T e1, e2; // 頂點E weight; // 邊的權值cout << "請輸入頂點數和邊數:" << endl;cin >> n >> m;cout << "請輸入各頂點:" << endl;for(i = 0; i < n; i++) {cin >> e1;insertVertex(e1); // 插入頂點}cout << "請輸入圖的各邊的信息:" << endl;i = 0;while(i < m) {cin >> e1 >> e2 >> weight;j = getVertexPos(e1);k = getVertexPos(e2);if(j == -1 || k == -1)cout << "邊兩端點信息有誤,請重新輸入!" << endl;else {insertEdge(j, k, weight); // 插入邊i++;}} // while }// 輸出有向圖中的所有頂點和邊信息 template <class T, class E> void Graphlnk<T, E>::outputGraph() {int n, m, i;T e1, e2; // 頂點E weight; // 權值Edge<T, E> *p;n = numVertices;m = numEdges;cout << "圖中的頂點數為" << n << ",邊數為" << m << endl;for(i = 0; i < n; i++) {p = nodeTable[i].adj;while(p != NULL) {e1 = getValue(i); // 有向邊<i, p->dest>e2 = getValue(p->dest);weight = p->cost;cout << "<" << e1 << ", " << e2 << ", " << weight << ">" << endl;p = p->link; // 指向下一個鄰接頂點}} }// 取位置為i的頂點中的值 template <class T, class E> T Graphlnk<T, E>::getValue(int i) {if(i >= 0 && i < numVertices)return nodeTable[i].data;return NULL; }// 返回邊(v1, v2)上的權值 template <class T, class E> E Graphlnk<T, E>::getWeight(int v1, int v2) {if(v1 != -1 && v2 != -1) {Edge<T , E> *p = nodeTable[v1].adj; // v1的第一條關聯的邊while(p != NULL && p->dest != v2) { // 尋找鄰接頂點v2p = p->link;}if(p != NULL)return p->cost;}return maxValue; // 邊(v1, v2)不存在,就存放無窮大的值 }// 插入頂點 template <class T, class E> bool Graphlnk<T, E>::insertVertex(const T& vertex) {if(numVertices == maxVertices) // 頂點表滿,不能插入return false;nodeTable[numVertices].data = vertex; // 插入在表的最后numVertices++;return true; }// 插入邊 template <class T, class E> bool Graphlnk<T, E>::insertEdge(int v1, int v2, E weight) {if(v1 >= 0 && v1 < numVertices && v2 >= 0 && v2 < numVertices) {Edge<T, E> *p = nodeTable[v1].adj; // v1對應的邊鏈表頭指針while(p != NULL && p->dest != v2) // 尋找鄰接頂點v2p = p->link;if(p != NULL) // 已存在該邊,不插入return false;p = new Edge<T, E>; // 創建新結點p->dest = v2;p->cost = weight;p->link = nodeTable[v1].adj; // 鏈入v1邊鏈表nodeTable[v1].adj = p;numEdges++;return true;}return false; }// 有向圖刪除頂點較麻煩 template <class T, class E> bool Graphlnk<T, E>::removeVertex(int v) {if(numVertices == 1 || v < 0 || v > numVertices)return false; // 表空或頂點號超出范圍Edge<T, E> *p, *s;// 1.清除頂點v的邊鏈表結點w 邊<v,w>while(nodeTable[v].adj != NULL) {p = nodeTable[v].adj;nodeTable[v].adj = p->link;delete p;numEdges--; // 與頂點v相關聯的邊數減1} // while結束// 2.清除<w, v>,與v有關的邊for(int i = 0; i < numVertices; i++) {if(i != v) { // 不是當前頂點vs = NULL;p = nodeTable[i].adj;while(p != NULL && p->dest != v) {// 在頂點i的鏈表中找v的頂點s = p;p = p->link; // 往后找}if(p != NULL) { // 找到了v的結點if(s == NULL) { // 說明p是nodeTable[i].adjnodeTable[i].adj = p->link;} else {s->link = p->link; // 保存p的下一個頂點信息}delete p; // 刪除結點pnumEdges--; // 與頂點v相關聯的邊數減1}}}numVertices--; // 圖的頂點個數減1nodeTable[v].data = nodeTable[numVertices].data; // 填補,此時numVertices,比原來numVertices小1,所以,這里不需要numVertices-1nodeTable[v].adj = nodeTable[numVertices].adj;// 3.要將填補的頂點對應的位置改寫for(int i = 0; i < numVertices; i++) {p = nodeTable[i].adj;while(p != NULL && p->dest != numVertices) // 在頂點i的鏈表中找numVertices的頂點p = p->link; // 往后找if(p != NULL) // 找到了numVertices的結點p->dest = v; // 將鄰接頂點numVertices改成v}return true; }// 刪除邊 template <class T, class E> bool Graphlnk<T, E>::removeEdge(int v1, int v2) {if(v1 != -1 && v2 != -1) {Edge<T, E> * p = nodeTable[v1].adj, *q = NULL;while(p != NULL && p->dest != v2) { // v1對應邊鏈表中找被刪除邊q = p;p = p->link;}if(p != NULL) { // 找到被刪除邊結點if(q == NULL) // 刪除的結點是邊鏈表的首結點nodeTable[v1].adj = p->link;elseq->link = p->link; // 不是,重新鏈接delete p;return true;}}return false; // 沒有找到結點 }// 取頂點v的第一個鄰接頂點 template <class T, class E> int Graphlnk<T, E>::getFirstNeighbor(int v) {if(v != -1) {Edge<T, E> *p = nodeTable[v].adj; // 對應鏈表第一個邊結點if(p != NULL) // 存在,返回第一個鄰接頂點return p->dest;}return -1; // 第一個鄰接頂點不存在 }// 取頂點v的鄰接頂點w的下一鄰接頂點 template <class T, class E> int Graphlnk<T, E>::getNextNeighbor(int v,int w) {if(v != -1) {Edge<T, E> *p = nodeTable[v].adj; // 對應鏈表第一個邊結點while(p != NULL && p->dest != w) // 尋找鄰接頂點wp = p->link;if(p != NULL && p->link != NULL)return p->link->dest; // 返回下一個鄰接頂點}return -1; // 下一個鄰接頂點不存在 }// 給出頂點vertex在圖中的位置 template <class T, class E> int Graphlnk<T, E>::getVertexPos(const T vertex) {for(int i = 0; i < numVertices; i++)if(nodeTable[i].data == vertex)return i;return -1; }// 當前頂點數 template <class T, class E> int Graphlnk<T, E>::numberOfVertices() {return numVertices; }#endif /* Graph_h */

2.AOE.h

#ifndef AOE_h #define AOE_h #include "Graph.h"// 計算關鍵路徑的算法 template <class T, class E> void CirticalPath(Graphlnk<T, E>& G) {int i, j, k, n;E Ae, Al, w;n = G.numberOfVertices(); // 圖的頂點數E *Ve = new E[n];E *Vl = new E[n];for(i = 0; i < n; i++) // 初始化最早開始事件時間Ve[i] = 0;// 正向計算Ve[i],時間Vi的最早可能開始時間:從源點V0到頂點Vi的最長路徑長度for(i = 0; i < n; i++) {j = G.getFirstNeighbor(i); // 鄰接頂點while(j != -1) { // 存在鄰接頂點w = G.getWeight(i, j);if(Ve[i] + w > Ve[j]) // 要等前面時間最長的活動完了,才可以進行j事件Ve[j] = Ve[i] + w;j = G.getNextNeighbor(i, j); // 下一個鄰接頂點}}// 逆向計算Vl[]Vl[n-1] = Ve[n-1]; // 最終完成事件時間for(j = n-2; j > 0; j--) {k = G.getFirstNeighbor(j);Vl[j] = Ve[n-1]; // 假設最大為Ve[n-1]while(k != -1) { // 存在鄰接邊w = G.getWeight(j, k);if(Vl[k] - w < Vl[j])Vl[j] = Vl[k] - w; // 事件最遲允許開始時間k = G.getNextNeighbor(j, k);}}for(i = 0; i < n; i++) { // 求各活動的Ae, A1j = G.getFirstNeighbor(i);while(j != -1) {Ae = Ve[i]; // 活動ak最早可能開始時間Al = Vl[j] - G.getWeight(i, j); // 時間j最遲可能開始時間-活動ak需要的時間if(Al == Ae)cout << "<" << G.getValue(i) << "," << G.getValue(j) << ">" << "是關鍵活動" << endl;j = G.getNextNeighbor(i, j);}}delete []Ve; // 釋放動態分配的空間delete []Vl; }#endif /* AOE_h */

3.main.cpp

#include "AOE.h"int main(int argc, const char * argv[]) {Graphlnk<char, int> G; // 聲明圖對象// 創建圖G.inputGraph();cout << "圖的信息如下:" << endl;G.outputGraph();// 調用計算關鍵路徑的函數cout << "關鍵路徑如下:" << endl;CirticalPath(G);return 0; }

測試數據:

9 11

0 1 2 3 4 5 6 7 8

0 1 6

0 2 4

0 3 5

1 4 1

2 4 1

3 5 2

4 6 9

4 7 7

5 7 4

6 8 2

7 8 4

?

測試結果:

?

總結

以上是生活随笔為你收集整理的C++ AOE网络的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。