最大流問題講解(Lingo)
第一節 圖論的基本知識
1. 圖的概念
定義 圖G(V,E)是指一個二元組(V(G),E(G)),其中:
(1)V(G)={v1,v2,…, vn}是非空有限集,稱為頂點集,
(2)E(G)是V(G)中的元素對(vi,vj)組成的集合稱為邊集。
圖G:V(G)={v1,v2,v3,v4}
E(G)= {e1,e2,e3,e4,e5,e6}
e3=(v1,v3)
若圖G的邊是有方向的,稱G是有向圖,有向圖的邊稱為有向邊或弧。
常用術語
邊和它的兩端點稱為互相關聯.
與同一條邊關聯的兩個端點稱為相鄰的頂點,
與同一個頂點關聯的兩條邊稱為相鄰的邊.
3)端點重合為一點的邊稱為環.
4) 若一對頂點之間有兩條以上的邊聯結,
則這些邊稱為重邊.
5)既沒有環也沒有重邊的圖,稱為簡單圖.
6) 若圖G的每一條邊e 都賦以一個實數w(e),
稱w(e)為邊e的權,
G連同邊上的權稱為賦權圖 ,
記為:G(V,E,W), W={w(e)| e∈E}
7) 圖G的中頂點的個數, 稱為圖G的階;
圖中與某個頂點相關聯的邊的數目,稱為該頂點的度。
8)完全圖:若無向圖的任意兩個頂點之間都存在著一條邊,
稱此圖為完全圖。
2.圖的矩陣表示
鄰接矩陣: (以下均假設圖為簡單圖).
圖G的鄰接矩陣是表示頂點之間相鄰關係的矩陣:A=(aij),
其中:
無向圖G
鄰接矩陣
A=(aij)
有向圖G
鄰接矩陣
A=(aij)
第二節 最大流問題
定義:設G(V,E)為有向圖,若在每條邊e上定義一個非負權c,
則稱圖G為一個網路,稱c為邊e的容量函式,記為c(e)。
若在有向圖G(V,E)中有兩個不同的頂點vs與vt ,
若頂點vs只有出度沒有入度,稱vs為圖G的源,
若頂點vt只有入度沒有出度,
稱vt為G的匯,
若頂點v 既不是源也不是匯,
稱為v中間頂點。
設u,v是網路G(V,E)的相鄰頂點,邊(u,v)上定義的函式f(u,v)
稱為邊(u,v)上的實際流量( u到v的流量 );
若對網路G(V,E)的任意相鄰頂點u,v 均成立: 0≤ f(u,v) ≤ c(u,v) ,
稱該網路為相容網路。
若v為網路G(V,E)的中間頂點,
有:
網路的總流量為從源vs 流出的總流量:
流入匯vt 總流量:
例1 分組交換技術在計算機網路中發揮著重要作用,資訊從源節點到目的節點不再需要一條固定的路徑,而是將其分割為幾組,通過不同的路徑傳輸到目的節點,目的節點再重新組合還原檔案。現考察如圖所示的網路,圖中兩節點間的數字表示兩交換機間可用的頻寬,此時從節點1到節點9的最大頻寬為多少?
設fij為從vi到vj的實際流量,得一個9階方陣:F=( fij)
記容量矩陣為:
Lingo程式碼:
sets: node/v1..v9/;
arc(node,node):c,f;
endsets
[OBJ]max=flow;
@for(node(i)|i#ne#1#and#i#ne#9:@sum(node(j):f(i,j))=@sum(node(j):f(j,i)));
@sum(node(j): f(1,j))=flow;
@sum(node(j): f(j,9))=flow;
@for(arc:@bnd(0,f,c));
data:
c=
0 2.5 0 5.6 6.1 0 0 0 0
0 0 7.1 0 0 3.6 0 0 0
0 0 0 0 0 0 0 3.4 0
0 0 0 0 4.9 0 7.4 0 0
0 2.4 0 0 0 7.2 5.7 0 0
0 0 3.8 0 0 0 0 5.3 4.5
0 0 0 0 0 3.8 0 0 6.7
0 0 0 0 0 0 0 0 7.4
0 0 0 0 0 0 0 0 0;
@text()=@table(f);
enddata
Lingo基礎:
//圖片中比較抽象,下面我用C語言的結構體類比一下
/*
集 ←→ 結構體
整合員 ←→ 結構體的域
集屬性 ←→ 結構體例項
*/
struct person {//person 相當於 setname
//sex, age 相當於整合員
char sex;
int age;
};
struct person xiaoming;//小明相當於成員屬性
xiaoming.sex = 'M';
xiaoming.age = 20;
#ne# not equal(不等於)若兩邊運算值不相等,返回邏輯值為1;
否則返回邏輯值為0;
#and# 僅當兩邊的引數都為1時,結果為1;
@bnd(L,x,U) 限制L≤x≤U
1.@for
該函式用來產生對整合員的約束。基於建模語言的標量需要顯式輸入每個約束,不過@for函式允許只輸入一個約束,然後LINGO自動產生每個整合員的約束。
例4.10 產生序列{1,4,9,16,25}
model:
sets:
number/1..5/:x;
endsets
@for(number(I): x(I)=I^2);
end
2.@sum
該函式返回遍歷指定的整合員的一個表示式的和。
例4.11 求向量[5,1,3,4,6,10]前5個數的和。
model:
data:
N=6;
enddata
sets:
number/1..N/:x;
endsets
data:
x = 5 1 3 4 6 10;
enddata
s=@sum(number(I) | I #le# 5: x);
end
答案: