網絡流初步

網絡流初步

文章目錄

  • 網絡流初步
    • 概念介紹
    • 最大流
    • 費用流

概念介紹

網絡流不同之處在于它的本質圖論,但是把圖論的某些概念換了一個說法而已,初步只要了解網絡流的各個概念就可以明白的很快。

下述概念是本人自己定義的,對于網絡流的題目做的還不多,后續會更正。

首先需要理解:網絡流其實是在一個有向圖中,從某個原點開始放水,水沿著管道最后流向匯點的過程,基于此就可以很好的理解一些概念和定理,而不需要十分嚴謹的證明(因為證明意義不大

流網絡: 對于一個 G(V,E)G(V,E)G(V,E) 的單向圖,我們稱為流網絡

容量C: 點和點之間的邊權成為容量

流量F: 通俗點說,點與點之間流過的水流量,和物理定義流量一致。一個很顯然的性質:F≤CF\le CFC 即流量不能超過容量

原點和匯點: 水流出的點,和水流入的點。

可行流: 全稱可以流進去的流量,F(u,v)F(u,v)F(u,v) 表示從 u 點流到 v 點的流量

流網絡的可行流:即從原點或者匯點流入或者流出的總流量 ∣F∣|F|F

最大流: 全稱最大可行流,比較抽象,實際意義就是:從原點可以流出的最大流量,或者是匯集到匯點的最大流量。

殘留網絡: 對于一個每條邊都確定流量F的流網絡,如果存在某條邊 C?F>0C-F>0C?F>0 ,即如果可以的話,還可以從 u→vu\to vuv 流動 C?FC-FC?F 的水,那么我們將這些差值重新構造一張圖,形成的網絡被稱為殘留網絡,十分形象,同時還會建立反向邊,不過權值變成 ?F-F?F ,可以理解為水反向流動。此時構成完整的殘存網絡。

增廣路: 在殘存網絡中,存在一條路徑使得從S到T,該條路徑流過的水>0,也就是路徑最小值大于零,則稱為該條路徑成為增廣路。

:對于原點S 和 匯點T,我們通過劃分將點集分成兩部分,滿足 S點集中點可以從S到達,T點集中點可以到達T,但是T和S不能在一個集合,此時我們成為是流網絡中的一個割。

割的容量: 即連接點集 S 和點集 T 的邊權的容量

割的流量: 同上,邊權的流量

最小割: 全稱最小割的容量。

結論

  • 如果殘留網絡不存在增廣路,此時流網絡的可行流最大,即最大流

    證明: 主觀十分好理解:如果不存在一種路徑使得水從原點流到匯點,那么此時說明不能再流動,那么此時就是最大流量

    證明充要:也很顯然,既然是最大流量,那么就不可能存在讓自己流量在增加的路

  • 如果殘留網絡不存在增廣路,那么一定存在一種割的兩個點集 S,TS,TS,T,滿足 ∣F∣=∑u∈S,v∈Tc(u,v)|F|=\sum_{u\in S,v\in T} c(u,v)F=uS,vT?c(u,v)

    證明:現在畫圖更好理解這句話的意思:
    在這里插入圖片描述

    公式含義就是粉色框的邊權的容量要等于流網絡的可行流。 y總的證明:

    我們這樣構造 S點集:在殘留網絡GfG_fGf? 中所有從S點出發邊權容量不是 0 的點,剩余點歸算于T點,那么對于這割的容量就是0,可以發現,這樣的集合是可以構造出來的,因為有這個GfG_fGf? 不存在增廣路的條件,那么所有的路徑至少存在一個邊權容量為0。

    那么因為每個割的殘留網絡容量為0,那么說明每條邊都是某條流過的路徑的最小值(或者是某些最小值的和,因為可能會存在距離S更近的某條邊殘余容量為0,這些流量之后恰好分開流向后面的最小值們,本質上是還是所有流過的路徑最小值的貢獻總和,可以理解為是所有的最小值邊成為了割),也就是該條路徑的流量,那么將這些流量加起來就是總流量。因為從S點流出的流量必須經過割中的所有邊權才能到達T,又因為每個邊的容量等于流量,所以滿足 ∣F∣=∑C(u,v)|F|=\sum C(u,v)F=C(u,v)

  • 如果存在兩個點集 S,TS,TS,T,滿足 ∣F∣=∑u∈S,v∈Tc(u,v)|F|=\sum_{u\in S,v\in T} c(u,v)F=uS,vT?c(u,v),那么∣F∣|F|F 一定是最大流

證明:很顯然,因為割的每條邊的流量完全等于容量(由2可知(因為不存在增廣路)),試想,我們將連接兩個點集的之間割的容量全部得到了(S,T 之間可傳遞的最大容量),那么此時的流量和就是最大流。

  • 最大流=最小割

    由上面的三個證明便可以得到,最大流 →\to 不存在增廣路 →\to 最小割 →\to 最大流

這是最重要的證明,便于以后的建邊和理解。

最大流

算法實現:

EK算法

算法思想:在圖中不斷找增廣路,然后對邊更改刪掉增光路,對答案造成貢獻,最后不存在增廣路就是答案。時間復雜度:O(nm2)O(nm^2)O(nm2),時間復雜度不會證明,不過可以滿足 n<10000 以下的級別

模板:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int read(){int x;scanf("%lld",&x);return x;}
const int B=1e6+10;
int p;
int n,m,S,T;
int head[1010];
int cnt;
struct node
{int u,v,nxt,w;
}e[B<<1];
void modify(int u,int v,int w)
{e[cnt].nxt=head[u];e[cnt].v=v;e[cnt].w=w;head[u]=cnt;cnt++;
} 
void add(int u,int v,int w)
{modify(u,v,w);modify(v,u,0);
}
int d[1010];
int pre[1010];
int vis[1010];
int inf=0x3f3f3f3f;
bool bfs()
{queue<int>q;memset(vis,0,sizeof(vis));q.push(S); vis[S]=1; d[S]=inf; while (!q.empty()){int u=q.front();q.pop();for (int i=head[u];i!=-1;i=e[i].nxt){int v=e[i].v;if (vis[v] || e[i].w==0) continue;d[v]=min(d[u],e[i].w);vis[v]=1;pre[v]=i;if (T==v) return 1;q.push(v);}}return 0;
}
int EK()
{int r=0;while (bfs()){r+=d[T];for (int i=T;i!=S;i=e[pre[i]^1].v){e[pre[i]].w-=d[T];e[pre[i]^1].w+=d[T];}}return r;
}
void work()
{cin>>n>>m>>S>>T;memset(head,-1,sizeof(head));for (int i=1;i<=m;i++){int u=read(),v=read(),c=read();add(u,v,c);}cout<<EK();
}
signed main()
{p=1;while (p--) work();return 0;
}

網絡流細節

雙向建邊的時候需要注意的地方

  • cnt從 0 開始,不是1
  • for 循環里,邊界 i!=-1 而不是 i!=0

費用流

費用流被稱為:最小費用最大流

每個流量上又添加了一個單位流量花費。要求在最大流的情況下花費最小。

寫法:把bfs找增廣路,改寫成SPFA找增廣路就可以

證明:

最終可以從s點到達T做出貢獻的路徑是一定的,每條路徑之間可能存在平替的現象,Bfs只是從中隨便選擇了幾條,但我們可以將其平替,如下圖

在這里插入圖片描述

這些路徑中,存在多種方案滿足條件,要想花費最小,直接貪心就可。以前之所沒有想明白,就可這張圖一樣,我想的是如果先把 6 的路徑找出來,最后就只剩下 2 的路徑才能成為8

不過我忘記了,還可以從 4 中走2,并不一定非要走4,所以這就不需要擔心當前選擇影響后續可選擇對象的問題了,因為當前的選擇不影響后續任何選擇,不會導致選擇對象數量發生變化,故可以直接貪心

模板

#include<bits/stdc++.h>
#define int long long
using namespace std;
int read(){int x;scanf("%lld",&x);return x;}
const int B=1e6+10;
int p;
int n,m,S,T;
int head[B];
int cnt;
struct node
{int u,v,nxt,c,w;
}e[B<<1];
void modify(int u,int v,int c,int w)
{e[cnt].nxt=head[u];e[cnt].v=v;e[cnt].c=c;e[cnt].w=w;head[u]=cnt;cnt++;
} 
void add(int u,int v,int c,int w)
{modify(u,v,c,w);modify(v,u,0,-w);
}
int d[5010];
int pre[5010];
int vis[5010];
int inf=0x3f3f3f3f;
int dis[5010];
bool bfs()
{queue<int>q;for (int i=1;i<=n;i++){vis[i]=0;dis[i]=inf;}q.push(S); vis[S]=1; d[S]=inf; dis[S]=0;while (!q.empty()){int u=q.front();q.pop();vis[u]=0;for (int i=head[u];i!=-1;i=e[i].nxt){int v=e[i].v;if (e[i].c==0) continue;if (dis[v]>dis[u]+e[i].w){dis[v]=dis[u]+e[i].w;pre[v]=i;d[v]=min(d[u],e[i].c);if (!vis[v]){vis[v]=1;q.push(v);}}}}return dis[T]!=inf;
}
void EK()
{int r=0;int sum=0;while (bfs()){r+=d[T];sum+=d[T]*dis[T];for (int i=T;i!=S;i=e[pre[i]^1].v){e[pre[i]].c-=d[T];e[pre[i]^1].c+=d[T];}}printf("%lld %lld", r,sum);
//	cout<<r<<" "<<sum<<"\n";
}
void work()
{cin>>n>>m>>S>>T;for (int i=1;i<=n;i++) head[i]=-1;for (int i=1;i<=m;i++){int u=read(),v=read(),c=read(),w=read();add(u,v,c,w);}EK();
}
signed main()
{p=1;while (p--) work();return 0;
}

r,sum);
// cout<<r<<" “<<sum<<”\n";
}
void work()
{
cin>>n>>m>>S>>T;
for (int i=1;i<=n;i++) head[i]=-1;
for (int i=1;i<=m;i++)
{
int u=read(),v=read(),c=read(),w=read();
add(u,v,c,w);
}
EK();
}
signed main()
{
p=1;
while (p–) work();
return 0;
}


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/95658.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/95658.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/95658.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[系統架構設計師]系統架構基礎知識(一)

[系統架構設計師]系統架構基礎知識&#xff08;一&#xff09; 一.計算機系統基礎知識 1.計算機系統概述 硬件軟件及網絡組成的系統 2.計算機硬件基礎知識 馮 諾依曼結構&#xff1a;運算器&#xff0c;控制器&#xff0c;存儲器&#xff0c;輸入設備&#xff0c;輸出設備 專用…

深入解析Java代理模式:靈活控制對象訪問的核心技術

在日常開發中&#xff0c;我們常遇到這樣的場景&#xff1a;需要控制對象訪問權限、優化高成本操作&#xff0c;或給方法添加額外功能&#xff08;如日志、事務&#xff09;。代理模式&#xff08;Proxy Pattern&#xff09; 正是解決這類問題的金鑰匙。作為結構型設計模式的代…

【學習筆記】Java并發編程的藝術——第9章 Java中的線程池

第9章 Java中的線程池 線程池優勢&#xff1a; ①減少資源消耗 ②提高響應速度 ③統一管理 9.1 線程池的實現原理 當任務來后 ①判斷核心線程池是否已滿&#xff0c;若未滿&#xff0c;創建一個核心線程來執行任務 ②若無空閑核心線程且核心線程已滿&#xff0c;則將任務放入任…

Mybatis學習筆記(九)

常見問題與解決方案 簡要描述&#xff1a;總結MyBatis-Plus開發過程中常見的問題、錯誤及其解決方案&#xff0c;幫助開發者快速定位和解決問題。 核心概念&#xff1a; 常見錯誤&#xff1a;開發中經常遇到的錯誤類型性能問題&#xff1a;性能相關問題的排查和解決配置問題&am…

數據類型 list

一、介紹類似于數組&#xff0c;順序表&#xff0c;deque結構圖特點&#xff1a;元素有序&#xff0c;元素允許重復由于頭尾高效插入刪除&#xff0c;可以模擬棧&#xff0c;隊列二、常見 list 命令1、lpush key elem [elem ...]頭插元素&#xff0c;返回值列表長度2、lrange k…

pyqt5無法顯示opencv繪制文本和掩碼信息

背景&#xff1a;pyqt5無法顯示opencv繪制的標簽和mask&#xff1b;我們在使用YOLO做實例分割做推理時&#xff0c;會使用opencv做后處理結果繪制&#xff08;含標簽繪制和掩碼繪制&#xff09;&#xff1b;結果opencv繪制的解碼卻無法在pyqt的解碼上面顯示。pyqt轉換代碼如下&…

如何生成嚴格遞增的分布式id?

本文字數&#xff1a;2604字預計閱讀時間&#xff1a;15分鐘01引言在現有分布式系統中&#xff0c;面對增長迅速的業務數據&#xff0c;id生成一直是非常重要的一環。而分布式系統的id生成方案需要滿足幾個重要特性&#xff1a;容錯高可用、高性能高并發、全局唯一。02技術背景…

【LeetCode】二叉樹相關算法題

目錄1、二叉樹介紹【1】核心概念【2】關鍵特性2、算法題【1】二叉樹的前序遍歷【2】二叉樹的后序遍歷1、二叉樹介紹 【1】核心概念 結構含義節點結構二叉樹由節點組成&#xff0c; 每個節點包含一個數據元素和最多兩個子節點&#xff1a;左子節點和右子節點根節點樹的頂部節點…

Vulnhub Deathnote靶機復現攻略

一、靶機安裝 下載地址&#xff1a;https://download.vulnhub.com/deathnote/Deathnote.ova 下載好后使用VB打開&#xff0c;配置如下 二、主機發現 使用相同連接方式的kali進行后續操作(172.16.2.7)根據mac地址進行確認。 nmap -sn 172.16.2.1/24 三、端口掃描 端口開放了…

DevEco Studio 6.0.0 元服務頁面跳轉失敗

背景&#xff0c;我使用最新的編輯器DevEco Studio 6.0.0&#xff0c;編寫一個元服務&#xff0c;發現使用跳轉頁面的時候失敗了&#xff01;然后查看官方文檔&#xff0c;兩種方式都測試了&#xff0c;發現都不行。 方法1&#xff1a;Navigation路由跳轉無效&#xff0c;見官方…

docker重啟或系統重啟后harbor自動啟動

docker重啟或系統重啟后harbor自動啟動docker重啟或系統重啟后harbor自動啟動方法 1&#xff1a;在 docker-compose.yml 中配置重啟策略&#xff08;推薦&#xff09;方法 2&#xff1a;創建 Systemd 服務&#xff08;更可靠&#xff09;方法 3&#xff1a;使用 Docker 的 Rest…

OpenZeppelin Contracts 架構分層分析

OpenZeppelin Contracts 是一個面向以太坊&#xff08;及兼容 EVM 的區塊鏈&#xff09;生態系統的??模塊化、安全性優先、標準兼容的智能合約庫??。其內部代碼按照功能職責與抽象層級&#xff0c;可系統性地劃分為多個邏輯層次。理解這些層次及其依賴關系&#xff0c;對于…

Java-JVM的內存模型

一.JVM內存模型JVM內存模型可以從進程生命周期和線程生命周期1.線程生命周期每個線程都會有自己各自一份數據&#xff0c;不會存在線程安全問題1.程序計數器指示當前線程執行的字節碼指令的行號&#xff0c;以便線程執行時可以回到正確的位置2.虛擬機棧線程私有的&#xff0c;與…

Highcharts Dashboards | 打造企業級數據儀表板:從圖表到數據駕駛艙

企業日常決策、產品運營、業務監控&#xff0c;越來越依賴數據驅動。而儀表板&#xff08;Dashboard&#xff09;作為匯總展示多維度信息的“數據駕駛艙”&#xff0c;已成為企業可視化的核心場景之一。如果你正在尋找一款能夠快速、靈活、安全構建儀表板的前端圖表工具&#x…

基于Java的Markdown轉Word工具(標題、段落、表格、Echarts圖等)

項目源于我們開發的一款基于大模型的報告生成工具。由于需要將 Markdown 格式的內容導出為 Word 文檔&#xff0c;而市面上缺乏合適的現成工具&#xff0c;所以決定自己開發一個Markdown轉Word的工具。 &#x1fa77;源碼地址&#xff1a;daydayup-zyn/md2doc-plus &#x1f…

Unity:PlayerPrefs筆記

寫在前面&#xff1a;寫本系列(自用)的目的是回顧已經學過的知識、記錄新學習的知識或是記錄心得理解&#xff0c;方便自己以后快速復習&#xff0c;減少遺忘。一、PlayerPrefs的基本方法1、存儲相關PlayerPrefs的數據存儲類似于鍵值對存儲&#xff0c;一個鍵對應一個值。Unity…

SQL tutorials

SQL Literature SQL運行在資料庫管理系統&#xff08;Database Management System&#xff09;&#xff0c;如MySQL&#xff0c;Postgre SQL&#xff0c;Microsoft SQL Server&#xff0c; Oracle&#xff0c;etc。 SQL練習平臺&#xff1a;https://sqliteviz.com/ EXAMPLE SQL…

MySQL快速恢復數據的N種方案完全教程

目錄 1. 理解MySQL數據恢復的核心邏輯 1.1 數據丟失的常見場景 1.2 MySQL的“救命稻草”:關鍵文件和機制 2. 方案一:利用全量備份+binlog實現點對點恢復 2.1 準備工作 2.2 恢復步驟 2.3 實戰案例 3. 方案二:利用InnoDB的崩潰恢復機制 3.1 崩潰恢復的原理 3.2 恢復步…

雙屏加固筆記本電腦C156-2:堅固與高效的完美融合

在當今數字化時代&#xff0c;筆記本電腦已成為人們工作和生活中不可或缺的工具。然而&#xff0c;對于一些特殊行業和惡劣環境下的應用場景&#xff0c;普通筆記本電腦往往難以滿足需求。此時&#xff0c;具備堅固耐用、高性能等特點的加固筆記本電腦應運而生。魯成偉業的雙屏…

Jenkins 環境部署

下載相關軟件&#xff1a;Jenkins 的安裝和設置 相關工具&#xff1a; Git : Git - Downloads java 17: Java Archive Downloads - Java SE 17.0.12 and earlier python : Download Python | Python.org jenkins、jenkins.war : Jenkins 的安裝和設置 將所有軟件安裝后&am…