ACM北大暑期課培訓第八天
今天學了有流量下界的網絡最大流,最小費用最大流,計算幾何。
有流量下界的網絡最大流
如果流網絡中每條邊e對應兩個數字B(e)和C(e), 分別表示該邊上的流量至少要是B(e),最多 C(e),那麽,在這樣的流網絡上求最大流,就是有下界的最大流問題。
這種網絡不一定存在可行流
思路:將下界“分離”出去,使問題轉換為下界為0的普通網絡流問題。
將原弧(u,v)分離出一條必要弧和一條非必要弧:
假設B(u,v)是下界,則分離出兩條弧: C1(u,v) = B(u,v) -- 必要弧
C2(u,v) = C(u,v) – B(u,v)
由於必要弧的有一定要滿流的限制,將必要弧“拉” 出來集中考慮
添加附加點x,y。想像一條不限上界的(x, y),用必要弧將它們“串”起來,即對於有向必要弧(u, v),添加 (u, x),(y, v),容量為必要弧容量。這樣就建立了一個等價的網絡。
去掉邊(x,y),添加由t到s的容量為正無窮大的邊,使y和 x分別成為新的源和新的匯。
若此圖上的最大流能夠占滿與Y相連的所有邊的容量(自 然也就會占滿所有連到x的邊的容量),那麽原圖上就存 在滿足上下界條件的可行流。若最大流不能夠占滿與Y相 連的所有邊的容量,則原圖不存在可行流。
新圖最大流若小於新圖中x的流入量之和,則原問題 無解
在新圖的最大流中,求出s流出的流量之和,記為 sum1
在做過一遍最大流的新圖的殘余網絡中,去掉t->s 以及s->t的邊,然後以s為源,t為匯再做一次最大流, 此時得到的流量 sum2,則 sum1+sum2就是在原圖 上滿足下界的最大流。
和x,y相連的邊不用處理,因為x,y實際上是只能流入 或只能流出的點,在圖中不起作用。
要想求出每條邊上的流量,怎麽辦?
在做第二次最大流之前,將圖備份到G2
經過兩次求最大流後,最後變成的殘余網絡是G
此時G2[i][j] – G[i][j] + LC[i][j] 就是 i->j上的流量
LC[i][j] 是i->j邊上的流量下界(下界是被滿足的)
處理網絡流題目要註意,如果有重邊,則要將重邊 上的容量和下界累加,合並成一條邊。
例題:POj 2396 Budget
題目: 現在有一個n*m的方陣,方陣裏面的數字未知,但是我們知道如下約束條件: 1> 每一行的數字的和 2> 每一列的數字的和 3> 某些格子裏的數,大小有限制。比如規定第2 行第3列的數字必須大於5(或必須小於3,或必須等於10等) 求解是否存在在滿足所有的約束的條件下用正數來填充該方陣的方案,若有,輸出填充後的方陣,否則輸出IMPOSSIBLE. 這道題可以轉化成容量有上下界的最大流問題,將方陣的行從1……n編號,列n+1……n+m編號,添加源點s=0和匯點t=n+m+1. 1>將源點和每一個行節點相連,相連所形成的邊的容量和下界置為該行所有數字的和 2>將每一個列節點和匯點相連,相連所形成的邊的容量和下界都置為該列所有數字的和 3>從每個行節點到每個列節點連邊,容量為無窮大 4> 如果u行v列的數字必須大於w,則邊<u,v+n>流量的下界是w+1 5> 如果u行v列的數字必須小於w,則邊<u,v+n>容量改為w-1 6> 如果u行v列的數字必須等於w,則邊<u,v+n>流量的下界和容量都是w找到的可行流(也是最大流),就是問題的解 本題trick: 1) W可能為負數,產生流量下界為負數的情況。應處理成0 2) 數據本身可能矛盾。比如前面說了 (2,1) =1,後面又說(2,1) = 10題目+思路
最小費用最大流
以下內容引自http://web.nuist.edu.cn/courses/dlxxxt/ch5/5.7.3.htm
http://jpkc.lzjtu.edu.cn/material3/xxxt/zxfyzdl.htm
設有一個網絡圖G(V,E),,V={s,a,b,c,…,s’},E中 的每條邊(i,j)對應一個容量c(i,j)與輸送單位流量所需費用 a(i,j)。如有一個運輸方案(可行流),流量為f(i,j),則 最小費用最大流問題就是這樣一個求極值問題: 其中F為G的最大流的集合,即在最大流中尋找一個費用 最小的最大流。
反復用spfa算法做源到匯的最短路進行增廣,邊權值為邊上單位費用。反向邊上的單位費用是負的。
直到無法增廣,即為找到最小費用最大流。
成立原因:每次增廣時,每增加1個流量,所增加的費用都是最小的。 (最短路) (最小費用==>路徑長度總和)
因為有負權邊(取消流的時候產生的),所以不能用迪傑斯特拉算法求最短路。(用SPFA)
二分圖最大匹配(網絡流問題)
計算幾何
基礎——點、線、面
解析幾何:列方程,解方程 (麻煩,特殊情況太多)
計算幾何:1.表示簡單
2.功能強大
3.特殊情況少,思維難度較低
4.函數可重復利用(即所謂的“模版”)
5.盡可能避免除法和三角函數,精度高,效率高
1 struct CVector///矢量表示 2 { 3 double x, y; 4 }; 5 ///表示從0點到 (x,y)的矢量。對矢量只關心方向 6 ///和長度,不關心(位置)起點終點 7 8 ///矢量的基本運算 9 CVector operator + (CVector p, CVector q)///矢量和 10 { 11 return CVector(p.x + q.x, p.y + q.y); 12 } 13 14 CVector operator -(CVector p, CVector q) 15 { 16 return CVector(p.x - q.x, p.y - q.y); 17 } 18 19 CVector operator *(double k, CVector p) 20 { 21 return CVector(k * p.x, k * p.y); 22 } 23 24 ///矢量的點積 25 ///性質:p·q=|p||q|cos<p,q> 26 ///a與b的點積,就是a的模乘以b在a上投影的模。若投影與a方向相反則為負值 27 ///其值的正負表示方向 28 ///功能:求同向還是異向;求投影;求出投影後用勾股定理求點到直線距離; 29 ///若a * b = 0,則 a和b垂直 30 double operator *(CVector p, CVector q) 31 { 32 return p.x * q.x + p.y * q.y; 33 } 34 35 ///矢量模長 36 ///用矢量與自身點積求模 37 double length(CVector p)///求矢量的模 38 { 39 return sqrt(p * p); 40 } 41 42 ///矢量單位化 43 ///將矢量除以自身的長度以得到同方向的單位矢量 44 CVector unit(CVector p) 45 { 46 return 1 / length(p) * p; 47 } 48 49 ///矢量的投影長度 50 ///矢量與該方向單位矢量的點積 51 ///註意:負數表示反方向 52 double project(CVector p, CVector n)///點積 53 { 54 return dot(p, unit(n)); 55 } 56 double dot(CVector p, CVector q) 57 { 58 return p.x*q.x+p.y*q.y; 59 } 60 61 ///矢量的叉積 62 ///性質:在二維情況中,|p×q|=|p||q|sin<p,q> 63 ///功能:求面積;求順時針方向還是逆時針方向;判斷是否在半平面上 64 ///用法:c = a ^ b; //a,b,c都是CVector對象 65 ///a×b 為有向面積,可正可負。 66 ///若a逆時針旋轉小於180度可到b,則結果為正,否則結果為負 67 double operator ^(CVector p, CVector q) 68 { 69 return p.x * q.y – q.x * p.y; 70 } 71 72 ///兩個矢量所圍成的三角形的面積 73 ///兩個矢量的叉積的一半 74 ///註意:得到的面積為有向面積,可能為負 75 double area(CVector p, CVector q) 76 { 77 return p^q / 2; 78 }代碼
矢量的點積:
未完...
ACM北大暑期課培訓第八天