前一段陣子學了極小的一部分網路流,這裡做一些總結,主要還是給自己看的a
給出乙個網路圖,以及其源點和匯點,求出其網路最大流。
第一行包含四個正整數n、m、s、t,分別表示點的個數、有向邊的個數、源點序號、匯點序號。
接下來m行每行包含四個正整數ui、vi、wi、fi,表示第i條有向邊從ui出發,到達vi,邊權為wi(即該邊最大流量為wi),單位流量的費用為fi。
一行,包含兩個整數,依次為最大流量和在最大流量情況下的最小費用。
ek:
#include#include#include
#include
#include
using
namespace
std;
const
int inf = 1
<< 30
;int
n,m,s,t;
struct
node
node[
200866
];struct
prepre[100866
];int top = 1,head[100866]; //
top必須從乙個奇數開始
inline void addedge(int u,int v,int
val)
inline
intread()
returnx;}
int inque[100866];//
點是訪問過里
inline bool bfs() //
是否有增廣路}}
return0;
}int
ek()
ans +=minn;
}return
ans;
}int
main()
printf("%d
",ek());
return0;
}
dinic:
按(+1)找反向邊,個人認為不大靠譜
#include#include#include
#include
#include
#include
#define maxn 20086
using
namespace
std;
const
int inf =1e9;
intn,m,s,t;
intcnt,max_flow;
int dep[maxn]; //
記錄每乙個節點的深度
int head[maxn]; //
存圖 int cur[maxn]; //
記錄路徑的
queueq;
struct
node
edge[maxn * 10
<< 1
];inline
void add_edge(int u,int v,int w) //
加邊建圖
inline
bool bfs(int s,int t) //
判斷是不是可以跑 }}
if(dep[t] return
true
;
else
return
false;}
inline
int dfs(int now,int t,int limit) //
limit就是乙個限制
//dfs的優點:在一次增廣的過程中,尋找多條增廣的路徑
}return
flow;
}void dinic(int s,int
t)int
main()
dinic(s,t);
printf("%d
",max_flow);
return0;
}
按(^1)找反向邊,注意cnt初始化為-1
#include#include#include
#include
#include
#include
#define maxn 20086
using
namespace
std;
const
int inf =1e9;
intn,m,s,t;
intu,v,w;
int cnt = -1; //
為了 ^ 的找反向邊做準備
intmax_flow;
int dep[maxn]; //
記錄每乙個節點的深度
int head[maxn]; //
存圖 int cur[maxn]; //
記錄路徑的
queueq;
struct
node
edge[maxn * 10
<< 1
];inline
void add_edge(int u,int v,int w) //
加邊建圖
inline
bool bfs(int s,int t) //
判斷是不是可以跑 }}
if(dep[t] return
true
;
else
return
false;}
inline
int dfs(int now,int t,int limit) //
limit就是乙個限制
//dfs的優點:在一次增廣的過程中,尋找多條增廣的路徑
}return
flow;
}void dinic(int s,int
t)int
main()
dinic(s,t);
printf("%d
",max_flow);
return0;
}
對於網路流,我們粗暴地每乙個節點的spfa顯然是較劣的
所以我們需要一種演算法來得到最大流量
首先介紹一下ek,同時它也是後面dinic的基礎
ek的著眼點就在於我們知道跑spfa是顯然不行的,那麼我們就可以針對這一點進行優化
優化的措施就是建立反向邊
反向邊的含義就是說給了一次反悔的機會,讓我們可以退回到當前狀態之前的狀態
這也是ek演算法的核心,既然我們不能直接跑,那麼我們就可以在建圖的過程中針對於每一條邊都建立一條它所對應的反向邊
我們就可以通過反向邊進行回溯,從而得到通過每乙個節點的最優解法(同時,這個的魯棒性可以幫助我們解決一些dinic解決不了的問題)
ek的跑法就是在spfa的過程中將每一種狀態的最優結果找出來,從而得到乙個這些結果裡面最大的收益
以上黃線標註的地方就是dinic針對於ek所改進的地方
因為在跑ek的時候做了大量的"無用功",那麼我們可不可以減少bfs的次數呢?
dinic就通過dfs將bfs的次數縮短了
這裡我們把bfs更改為bool型別,來判斷可不可以向下流
初始化dep[t] = 0x7f
然後判斷假如可以流的話,那麼dep[t]肯定是小於這個數值的(哪有圖0x7f深度的)
然後我們可以知道這個流可不可以向下流動
然後我們就可以在bfs可行的基礎上進行dfs了
dfs的優點:在一次增廣的過程中,尋找多條增廣的路徑
這樣肯定是優於全跑一遍的
完結
網路流之最大流
網路流之最大流 一 問題引入。有n個排水口,不同的排水口之間有m條水管連線,水一開始從源點s流出,最終到達t。每條邊 水管 都有乙個最大的流量。除了s,t外,每個排水口的流入量都要等於流出量,詢問最多能有多少水到達終點t 如圖所示 即poj 1273 可以將問題進行如下整理 1 用c e 表示每條邊...
網路流之最大流
因為網上介紹網路流和最大流理論的文章非常的多,也都解釋的非常清晰並附帶 再加上繪圖技術不佳,語文表達極差,就只講解一下程式實現部分。想看理論講解及演算法正確性證明的讀者可以上網搜一搜,這裡推薦一篇部落格,鏈結如下 那麼,既然網上的資源那麼多,為什麼還要寫這篇部落格呢?一是為了湊數做筆記,二是網上的許...
網路流之 最大流
最大流演算法是網路流中基礎的演算法,解決的方法有很多,比如ek,dinic,sap等等,在這裡介紹一下ek演算法。從源點s開始廣度優先尋找一條到t的路徑,計算出這條路徑的最大流量 短板效應 l,回溯,將這條路徑的每條邊的最大流量減去l,然後新增反向邊,容量為l,網路流的最大流max l。當找不到從s...