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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【文文殿下】网络流学习笔记

發(fā)布時間:2024/4/13 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【文文殿下】网络流学习笔记 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最大流算法

Dinic

一個網(wǎng)絡(luò)的割:存在一個邊集,刪去集合里的邊時,S-T不再連通

最小割

所有割中邊權(quán)之和最小的

最小割-最大流定理

最小割等于最大流

二分圖匹配

\(M\)為邊集\(E\)的一個子集,如果對于任何一個點,都最多被\(M\)中一條邊覆蓋,則成\(M\)為一個匹配。

最大匹配

使\(|M|\)最大的一個匹配(可能有多個)

最大匹配求法

源點S向所有X連邊,Y向T連邊,容量均為1,原始圖上邊容量均為1,最大流=最大匹配。

二分圖最小頂點覆蓋

\(V'\)是點集\(V\)的一個子集,對于任意一條邊,至少有一端在\(V'\)內(nèi)。

最小的一個\(V'\)被稱作最小頂點覆蓋

最大匹配=最小頂點覆蓋

證明:若有一條邊未覆蓋,則匹配+1,與最大匹配矛盾

二分圖最大獨立集

\(V'\)\(G\)的一個獨立集,當且僅當對于任何一條邊,它至少有一端不在\(V'\)內(nèi)

最大獨立集大小等于\(|V|-\)最大匹配

證明:最小割。若(S,x)為割邊,則在\(V'\)中刪去x。y同理。

有向圖最小路徑覆蓋

用盡可能少的簡單路徑覆蓋整張圖。特殊的:一個點也是一條簡單路徑。

二分圖建模:把每個點\(x\)拆成\(x_1,x_2\),分別屬于X,Y.

對原圖一條邊,(x,y),鏈接(\(x_1,y_2\))

易證:最小路徑覆蓋=\(|V|-\)最大匹配。

X中未被匹配的點是每條路徑的起點

二分圖點權(quán)最大獨立集

最大權(quán)獨立集=\(\sum value(x) -\)最小權(quán)頂點覆蓋

最小權(quán)覆蓋=最大匹配=最小割=最大流(原圖的邊流量為無窮大)

建圖:S向所有X連邊,容量為value(x),所有的Y向T連邊,容量為value(y) ,原圖中的邊容量為無窮大

最大權(quán)閉合子圖

\(U\)\(G\)的一個子圖,x屬于\(U\) 當且僅當對于任何一條邊(x,y),y也屬于\(U\),那么\(U\)\(G\)的一個閉合子圖

權(quán)值和最大的閉合子圖稱為最大權(quán)閉合子圖(權(quán)值有正有負)

求法:建立源點S,向所有x(value(x)>0)連邊,容量為value(x),建立匯點T,所有y(value(y)<0)向T連邊,容量為-value(y),對于原圖中的邊(x,y),在x,y之間連一條容量為無窮大的邊。

最大權(quán)閉合子圖=\(\sum_{value(x)>0} value(x) -\) 最小割

證明:

若選了一個點x,則他的后繼一定會選(最大流),滿足閉合子圖。

若一個(S,x)為割邊,說明(S,x)滿流,則選了x,他的后繼付出的代價一定不小于x的權(quán)值,即x的貢獻小于等于0

有節(jié)點容量的最大流

建圖:對于每一個點x拆成兩個點\(x_1,x_2\),對于所有入邊,鏈接\(x_1\)出邊從\(x_2\)出,\(x_1,x_2\)之間鏈接一條容量為節(jié)點容量的邊

上下界網(wǎng)絡(luò)流

每條邊有流量上界和流量下界

建圖:先建新源點S1,新匯點T1,對于一條邊(x,y) ,從x到y(tǒng)連一條\(c(e)-l(e)\)的邊,從S1向y連一條\(l(e)\)的邊,從x向T1連一條\(l(e)\)的邊。

建一條從T到S容量為k的邊。

存在可行流:從S1出發(fā)的所有邊都滿流。

最小流:二分K,存在可行流,最小的K即為最小流

最大流:先跑可行流。跑完以后,把自己加入的必要弧刪去,再恢復(fù)源匯,嘗試增廣S-T

費用流

算法:ZKW費用流

板子

最大流(BZOJ1694)

#include<cstdio> #include<cstring> #include<queue> const int maxn = 1010; const int maxm = 2e5+10; const int inf = 0x3f3f3f3f; int n,k,S,T,wet[maxm],nxt[maxm],to[maxm],hd[maxn],cnt=1,dis[maxn],cur[maxn]; std::queue<int> Q; inline void add(int u,int v,int w) {nxt[++cnt]=hd[u];hd[u]=cnt;to[cnt]=v;wet[cnt]=w; } inline bool bfs(void) {for(int i = 0;i<=T;++i) cur[i]=hd[i];memset(dis,0,sizeof dis);dis[S]=1;Q.push(S);while(!Q.empty()) {int u = Q.front();Q.pop();for(int i = hd[u];i;i=nxt[i]){ int nx = to[i];if(!dis[nx]&&wet[i]>0) {dis[nx]=dis[u]+1;Q.push(nx);}}}return dis[T]!=0; } inline int dfs(int u,int flow) {if(u==T) return flow;int tmp = 0;for(int &i = cur[u];i;i=nxt[i]) {int nx = to[i];if(dis[nx]==dis[u]+1&&wet[i]>0) {int ret = dfs(nx,std::min(flow,wet[i]));if(ret<0) ret=0;flow-=ret;tmp+=ret;wet[i]-=ret;wet[i^1]+=ret;if(flow==0) break;}}return tmp; } inline int dinic(void) {int flow = 0;while(bfs()) {flow+=dfs(S,inf);}return flow; } int main() {scanf("%d%d",&n,&k);for(int i = 0;i<k;++i) {int x,y;scanf("%d%d",&x,&y);add(x,n+y,1);add(n+y,x,0);}S = 0;T = n+n+1;for(int i = 1;i<=n;++i) {add(S,i,1);add(i,S,0);}for(int i = n+1;i<=n+n;++i) {add(i,T,1);add(T,i,0);}printf("%d",dinic());return 0; }

費用流

#include<cstdio> #include<cstring> #include<queue> typedef long long ll; const int maxn = 5050,maxm=1e5+10; const int inf = 0x3f3f3f3f; int n,m,S,T,cnt=1,wet[maxm],fee[maxm],hd[maxn],nxt[maxm],to[maxm]; int dis[maxn],cur[maxn]; bool vis[maxn]; std::queue<int> Q; inline void add(int u,int v,int w,int f) {nxt[++cnt]=hd[u];to[cnt]=v;wet[cnt]=w;fee[cnt]=f;hd[u]=cnt; } inline bool spfa(void) {memset(dis , 0x3f3f3f3f , sizeof dis);memset(vis, 0 , sizeof vis);for(int i = 1;i<=n;++i) cur[i]=hd[i];Q.push(S);dis[S]=0;while(!Q.empty()) {int u = Q.front();Q.pop();vis[u]=0;for(int i = hd[u];i;i=nxt[i]) {int nx = to[i];if(dis[nx]>dis[u]+fee[i]&&wet[i]) {dis[nx]=dis[u]+fee[i];if(!vis[nx]) {Q.push(nx);vis[nx]=1;}}}}return dis[T]!=dis[0]; } inline int dfs(int u,int c,int &flow ,ll &ans) {vis[u]=1;if(u==T) {flow+=c;ans+=dis[u]*c;return c;}int tmp = 0;for(int &i = cur[u];i;i=nxt[i]) {int nx = to[i];if(!vis[nx]&&wet[i]>0&&dis[nx]==dis[u]+fee[i]) {int t = dfs(nx,std::min(c,wet[i]),flow,ans);wet[i]-=t;wet[i^1]+=t;tmp+=t;c-=t;}}return tmp; } inline void dinic(void) {int flow = 0;ll ans = 0;while(spfa()) {vis[T]=1;while(vis[T]) {vis[T]=0;dfs(S,inf,flow,ans);}}printf("%d %lld\n",flow,ans);return; } int main() {scanf("%d%d%d%d",&n,&m,&S,&T);for(int i = 0;i<m;++i) {int u,v,w,f;scanf("%d%d%d%d",&u,&v,&w,&f);add(u,v,w,f);add(v,u,0,-f);}dinic();return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/Syameimaru/p/10117145.html

總結(jié)

以上是生活随笔為你收集整理的【文文殿下】网络流学习笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。