圖論---網絡流

最大流

EdmondsKarp

bfs找路罗丰,途中記錄前驅節(jié)點
讓后從匯點遍歷到起點,找到最小flow
再次遍歷,更新沿途邊
累加答案,繼續(xù)bfs

#define mem(x,y) memset(x,y,sizeof(x))
#define SIZE 1005
const int INF=0x3f3f3f3f;
int G[SIZE][SIZE],pre[SIZE];
bool vst[SIZE];
bool bfs(int s,int t){
    queue<int> que;
    mem(vst,0);
    mem(pre,-1);
    pre[s]=s;
    vst[s]=true;
    que.push(s);
    while (!que.empty()) {
        int u=que.front();que.pop();
        for(int i=s;i<=t;++i){//遍歷所有點
            if(G[u][i]&&!vst[i]){
                pre[i]=u;
                vst[i]=true;
                if(i==t)return true;
                que.push(i);
            }
        }
    }
    return false;
}
int EK(int s,int t){
    int ans=0;
    while (bfs(s,t)) {
        int minflow=INF;
        for(int i=t;i!=s;i=pre[i]){
            minflow=min(minflow,G[pre[i]][i]);
        }
        for(int i=t;i!=s;i=pre[i]){
            G[pre[i]][i]-=minflow;
            G[i][pre[i]]+=minflow;
        }
        ans+=minflow;
    }
    return ans;
}

dinic

多路增廣+當前弧優(yōu)化
建圖時候建反向邊(前向星邊id從0開始寇僧,這樣edge[i^1]就是反邊)
首先bfs分層,維護每個點到匯點的距離(每個邊距離都看做1)
然后對分過層的圖dfs沸版,每找到一條通路嘁傀,沿途邊邊權減去流量,反邊加上流量视粮,反復找直到沒有
再次bfs直到沒有
for(int &i=curedge[u];i!=-1;i=edge[i].nxt)
這句當前弧優(yōu)化可能看不懂细办,代碼中有詳細注釋
head[] edge[] 是鏈式前向星
curedge[] 當前弧優(yōu)化使用

#include <queue>
#include <string.h>
#define mem(x,y) memset(x,y,sizeof(x))
#define SIZE 1000
struct node{
    int v,nxt,w;//指向那個點 下條邊id 權值
}edge[SIZE*2];
int head[SIZE],curedge[SIZE],dis[SIZE],ecnt,s,t;
inline void init(){
    ecnt=0;//從偶數開始都行
    mem(head,-1);
}
inline void addedge(int u,int v,int w){
    edge[ecnt].v=v;
    edge[ecnt].w=w;
    edge[ecnt].nxt=head[u];
    head[u]=ecnt;
    ecnt++;
    swap(u,v);//添加反邊
    edge[ecnt].v=v;
    edge[ecnt].w=0;
    edge[ecnt].nxt=head[u];
    head[u]=ecnt;
    ecnt++;
}
bool bfs(){
    mem(dis,-1);//不能少
    dis[t]=0;//s是起點,t是終點蕾殴,分層
    queue<int> que;
    que.push(t);
    while(!que.empty()){
        int u=que.front();que.pop();
        for(int i=head[u];i!=-1;i=edge[i].nxt){
            if(dis[edge[i].v]==-1&&edge[i^1].w>0){
                dis[edge[i].v]=dis[u]+1;
                que.push(edge[i].v);
            }
        }
    }
    return dis[s]!=-1;//沒有辦法從s到t返回false
}
int dfs(int u,int v,int flow){
    if(u==t)return flow;
    int delta=flow;//表示前面輸送過來的流量有多少被擋住了笑撞,初始化為所有
    for(int &i=curedge[u];i!=-1;i=edge[i].nxt){
        //當前弧優(yōu)化,& 引用是重點
        if(dis[u]==dis[edge[i].v]+1&&edge[i].w>0){
            int d=dfs(edge[i].v,v,min(delta,edge[i].w));
            edge[i].w-=d;edge[i^1].w+=d;
            delta-=d;//可以放行d的流量钓觉,被擋住的流量變少了
            if(delta==0)break;//這句對當前弧優(yōu)化很重要茴肥,這時進來的流量全都放行了,那么當前這條路可能剛好被填滿议谷,也可能還有寬裕(如果delta炉爆!=0,說明這條路肯定占滿了)
            //因為可能有寬裕卧晓,所以這條路以后還要走芬首,這時候break;curedge[u]=i,前面的路因為都滿了逼裆,所以直接舍去郁稍,下次到這個點直接從第i個邊開始,這就是當前弧優(yōu)化胜宇。
        }
    }
    return flow-delta;//送進來的 - 擋住的 = 有效流量
}
int dinic(){
    int ans=0;
    while (bfs()) {//分層(計算距離)
        for(int i=s;i<=t;i++)//每bfs一次耀怜,層次就刷新,所以也要重置當前弧
            curedge[i]=head[i];
        ans+=dfs(s,t,INF);//從點1到點n最大流桐愉,輸入流量無窮大
    }
    return ans;
}

費用流

spfa

求最小費用最大流
建邊時候反邊cost是原來的負數
用spfa求出一條s到t的最短路财破,途中
pre[]數組記錄當前點是從哪個邊過來的(放了一個邊id)
然后通過pre[]從t一直遍歷到s,找到途中最小流量Min
再遍歷一次从诲,更新途中邊的容量左痢,更新答案
再次spfa直到沒有通路

#include <queue>
#include <string.h>
#define mem(x,y) memset(x,y,sizeof(x))
#define SIZE 1000
struct node{
    int v,nxt,cap,cost;//指向那個點 下條邊id 流通容量 這條路花費(看情況有時候是單價,記得改dfs里面的跟新)
}edge[40010];
int head[SIZE],dis[SIZE],pre[SIZE],ecnt,s,t;
bool vst[SIZE];
inline void init(){
    ecnt=0;//從偶數開始都行
    mem(head,-1);
}
inline void addedge(int u,int v,int cap,int cost){
    edge[ecnt].v=v;
    edge[ecnt].cap=cap;
    edge[ecnt].cost=cost;
    edge[ecnt].nxt=head[u];
    head[u]=ecnt;
    ecnt++;
    swap(u,v);//添加反邊
    edge[ecnt].v=v;
    edge[ecnt].cap=0;
    edge[ecnt].cost=-cost;//注意反邊花費為負
    edge[ecnt].nxt=head[u];
    head[u]=ecnt;
    ecnt++;
}
bool spfa(){
    mem(dis,INF);//不能少
    mem(vst,0);
    mem(pre,-1);
    dis[s]=0;//s是起點,t是終點俊性,分層
    vst[s]=true;
    queue<int> que;
    que.push(s);
    while(!que.empty()){
        int u=que.front();que.pop();
        vst[u]=false;
        for(int i=head[u];i!=-1;i=edge[i].nxt){
            if(dis[u]+edge[i].cost<dis[edge[i].v]&&edge[i].cap>0){
                //通過點u更短
                dis[edge[i].v]=dis[u]+edge[i].cost;
                pre[edge[i].v]=i;
                if(!vst[edge[i].v]){
                    vst[edge[i].v]=true;
                    que.push(edge[i].v);
                }
            }
        }
    }
    return pre[t]!=-1;//沒有辦法從s到t返回false
}
int mfmc(int & cost){//cost 按引用更新
    int flow=0; cost=0;
    while (spfa()) {
        int Min=INF;
        for(int i=pre[t];i!=-1;i=pre[edge[i^1].v]){//i是邊的id略步,得到另一個頂點edge[i^1].v
            if(Min>edge[i].cap){
                Min=edge[i].cap;
            }
        }
        for(int i=pre[t];i!=-1;i=pre[edge[i^1].v]){
            edge[i].cap-=Min;
            edge[i^1].cap+=Min;

        }
        cost+=dis[t]*Min;
        flow+=Min;
    }
    return flow;
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市定页,隨后出現(xiàn)的幾起案子趟薄,更是在濱河造成了極大的恐慌,老刑警劉巖典徊,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杭煎,死亡現(xiàn)場離奇詭異,居然都是意外死亡宫峦,警方通過查閱死者的電腦和手機岔帽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來导绷,“玉大人犀勒,你說我怎么就攤上這事⊥浊” “怎么了贾费?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長檐盟。 經常有香客問我褂萧,道長,這世上最難降的妖魔是什么葵萎? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任导犹,我火速辦了婚禮,結果婚禮上羡忘,老公的妹妹穿的比我還像新娘谎痢。我一直安慰自己,他們只是感情好卷雕,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布节猿。 她就那樣靜靜地躺著,像睡著了一般漫雕。 火紅的嫁衣襯著肌膚如雪滨嘱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天浸间,我揣著相機與錄音太雨,去河邊找鬼。 笑死魁蒜,一個胖子當著我的面吹牛囊扳,可吹牛的內容都是我干的煤墙。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼宪拥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铣减?” 一聲冷哼從身側響起她君,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎葫哗,沒想到半個月后缔刹,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡劣针,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年校镐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捺典。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡鸟廓,死狀恐怖,靈堂內的尸體忽然破棺而出襟己,到底是詐尸還是另有隱情引谜,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布擎浴,位于F島的核電站员咽,受9級特大地震影響,放射性物質發(fā)生泄漏贮预。R本人自食惡果不足惜贝室,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仿吞。 院中可真熱鬧滑频,春花似錦、人聲如沸茫藏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽务傲。三九已至凉当,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間售葡,已是汗流浹背看杭。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留挟伙,地道東北人楼雹。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贮缅。 傳聞我的和親對象是個殘疾皇子榨咐,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內容

  • 現(xiàn)實生活中有很大一類問題可以用簡潔明了的圖論語言來描述,可以轉化為圖論問題谴供。 相關定義 圖可以表示為G=(V, E...
    芥丶未央閱讀 1,674評論 0 7
  • 數據結構學不好块茁,c++就到后面會很迷,數據結構真滴很重要啊桂肌,上機題一定要認真做数焊,緊密的和實際操作的代碼聯(lián)系在一起是...
    Nancy_Shi閱讀 718評論 0 4
  • 一些概念 數據結構就是研究數據的邏輯結構和物理結構以及它們之間相互關系,并對這種結構定義相應的運算崎场,而且確保經過這...
    Winterfell_Z閱讀 5,695評論 0 13
  • 這個圣誕節(jié)假期谭跨,我給孩子的告誡干厚,同時也是對自己的告誡:你把時間花在了這里,就不可能花在那里饺蚊。上帝最大的公平是萍诱,所有...
    摸魚哥閱讀 1,164評論 0 0
  • 資本通過投資其他企業(yè)獲得回報裕坊,我認為最核心的能力是風險定價能力。如果一個團隊的人員構成都是偏向某個方向燕酷、專...
    劉朔_北京閱讀 140評論 0 0