1. 程式人生 > >(模板題)loj #127. 最大流 加強版(hlpp)

(模板題)loj #127. 最大流 加強版(hlpp)

最大流hlpp模板(原作者是xehoth,我就改了改拿來用用)

請根據題目要求做修改。

Note:可將vector改為鏈式前向星,程式碼我就不貼出來了,如有需要請私信我。

update(2018.9.29):

算是對這個板子的總結。

在檢驗板子的時候發現這個東西跑網路流時間下限較高,但上限小,適合跑邊數多的圖,畢竟O(n^{2}m^{\frac{1}{2}}),時間也很穩定,對於一些隨機圖而言dinic,isap跑得比它快。

個人認為:

vector存圖適用於邊多點少,跑的比前向星快。

而前向星適用於邊少點多,跑的比vector快。

但只是個人猜測,沒有任何證明。

速度對比(hdu 4280):

從上到下依次是:

不帶fastio的dinic、不帶fastio的hlpp(前向星)、不帶fastio的hlpp(vector)、帶fastio的dinic、帶fastio的hlpp(vector)、帶fastio的hlpp(前向星)

可見這東西的速度有多可怕了,但是這個東西應該屬於娛樂向,因為現場賽靠譜的出題人出個網路流基本不會卡dinic,否則就是寫殘了、板子問題、圖沒建對、這題就不是用網路流做的等等。

示例程式:

/**
 * Copyright (c) 2017-2018, xehoth
 * All rights reserved.
 * 25-01-2018
 * HighestLabelPreflowPush
 *
 * updated 05-02-2018
 * globalRelabel only once
 *
 * updated 03-03-2018
 * fix INF
 * @author xehoth
 */
#include <bits/stdc++.h>
#define INF INT_MAX
using namespace std;
struct node
{
    int v,cap,index;
};
vector<node>edge[1203];
vector<int>List[1203];
vector<list<int>::iterator>listit;
list<int>dlist[1203];
int highest,highestActive,vis[1203],excess[1203],height[1203];
void insert(int u,int v,int cap)
{
    edge[u].push_back(node{v,cap,edge[v].size()});
    edge[v].push_back(node{u,0,edge[u].size()-1});
}
void globalRelabel(int n,int t)
{
    int u,i,hp,v,index;
    queue<int>q;
    for(i=0;n>=i;i++)
    {
        height[i]=n;
    }
    height[t]=0;
    memset(vis,0,sizeof(vis));
    q.push(t);
    while(q.empty()==0)
    {
        u=q.front();
        q.pop();
        for(i=0;edge[u].size()>i; i++)
        {
            v=edge[u][i].v;
            index=edge[u][i].index;
            if(height[v]==n&&edge[v][index].cap>0)
            {
                height[v]=height[u]+1;
                vis[height[v]]++;
                q.push(v);
                hp=v;
            }
        }
    }
    for(i=0;n>=i;i++)
    {
        List[i].clear();
        dlist[i].clear();
    }
    for(i=0;n>i;i++)
    {
        if(height[i]<n)
        {
            listit[i]=dlist[height[i]].insert(dlist[height[i]].begin(),i);
            if(excess[i]>0)
            {
                List[height[i]].push_back(i);
            }
        }
    }
    highest=height[hp];
    highestActive=height[hp];
}
void push(int u,node &e)
{
    int v,df;
    v=e.v;
    df=min(excess[u],e.cap);
    e.cap=e.cap-df;
    edge[v][e.index].cap=edge[v][e.index].cap+df;
    excess[u]=excess[u]-df;
    excess[v]=excess[v]+df;
    if(excess[v]>0&&excess[v]<=df)
    {
        List[height[v]].push_back(v);
    }
}
void discharge(int n,int u)
{
    int i,nh,v,cap,h;
    nh=n;
    for(i=0;edge[u].size()>i;i++)
    {
        v=edge[u][i].v;
        cap=edge[u][i].cap;
        if(cap>0)
        {
            if(height[u]==height[v]+1)
            {
                push(u,edge[u][i]);
                if(excess[u]==0)
                {
                    return;
                }
            }
            else
            {
                nh=min(nh,height[v]+1);
            }
        }
    }
    h=height[u];
    if(vis[h]==1)
    {
        for(i=h;highest>=i;i++)
        {
            for(list<int>::iterator it=dlist[i].begin();it!=dlist[i].end();it++)
            {
                vis[height[*it]]--;
                height[*it]=n;
            }
            dlist[i].clear();
        }
        highest=h-1;
    }
    else
    {
        vis[h]--;
        listit[u]=dlist[h].erase(listit[u]);
        height[u]=nh;
        if(nh==n)
        {
            return;
        }
        vis[nh]++;
        listit[u]=dlist[nh].insert(dlist[nh].begin(),u);
        highestActive=nh;
        highest=max(highest,highestActive);
        List[nh].push_back(u);
    }
}
int hlpp(int n,int s,int e)
{
    int i,u;
    if(s==e)
    {
        return 0;
    }
    highestActive=0;
    highest=0;
    memset(height,0,sizeof(height));
    height[s]=n;
    listit.resize(n);
    for(i=0;n>i;i++)
    {
        if(i!=s)
        {
            listit[i]=dlist[height[i]].insert(dlist[height[i]].begin(),i);
        }
    }
    memset(vis,0,sizeof(vis));
    vis[0]=n-1;
    memset(excess,0,sizeof(excess));
    excess[s]=INF;
    excess[e]=-INF;
    for(i=0;edge[s].size()>i;i++)
    {
        push(s,edge[s][i]);
    }
    globalRelabel(n,e);
    while(highestActive>=0)
    {
        if(List[highestActive].empty()==1)
        {
            highestActive--;
            continue;
        }
        u=List[highestActive].back();
        List[highestActive].pop_back();
        discharge(n,u);
    }
    return excess[e]+INF;
}
int main()
{
    int n, m, s, t;
    scanf("%d %d %d %d",&n,&m,&s,&t);
    for (int i = 0, u, v, f; i < m; i++)
    {
        scanf("%d %d %d",&u,&v,&f);
        insert(u, v, f);
    }
    printf("%d",hlpp(n + 1, s, t));
    return 0;
}

相關推薦

(模板)loj #127. 加強(hlpp)

最大流hlpp模板(原作者是xehoth,我就改了改拿來用用) 請根據題目要求做修改。 Note:可將vector改為鏈式前向星,程式碼我就不貼出來了,如有需要請私信我。 update(2018.9.29): 算是對這個板子的總結。 在檢驗板子的時候發現這個東西

LOJ 101 (ISAP 模板

span ins bfs 最大流 spa nbsp space end pan 開long long的最大流 #include<bits/stdc++.h> using namespace std; const long long MAXN = 4000010

洛谷P3376【模板】網絡  Dinic模板

span -c -s blog name sca print 技術 pop 之前的Dinic模板照著劉汝佳寫的vector然後十分鬼畜跑得奇慢無比,雖然別人這樣寫也沒慢多少但是自己的就是令人捉急。 改成鄰接表之後快了三倍,雖然還是比較慢但是自己比較滿意了。雖然一開始ecnt

洛谷P3376 【模板】網絡

規模 ostream style 一次 ios 分層 nic i++ %d P3376 【模板】網絡最大流 題目描述 如題,給出一個網絡圖,以及其源點和匯點,求出其網絡最大流。 輸入輸出格式 輸入格式: 第一行包含四個正整數N

luogu3376 【模板】網絡 dinic

truct out ios div std main pty stream add 當前弧優化、單路增廣 #include <iostream> #include <cstring> #include <cstdio> #include

洛谷 P3376 【【模板】網絡

mem oid div pty ack turn color print from 題目描述 如題,給出一個網絡圖,以及其源點和匯點,求出其網絡最大流。 輸入 第一行包含四個正整數N、M、S、T,分別表示點的個數、有向邊的個數、源點序號、匯點序號。 接下來M行每行包含三個

[P3376]【模板】網絡

scanf sca sdi using pac ret c++ push clu 題意 最大流模板 思路 Dinic 代碼 我放棄了 #include <bits/stdc++.h> using namespace std; #defin

經典的POJ1273(網路) 【之Dinic演算法】POJ1273 【 & 當前弧優化 & 】

http://poj.org/problem?id=1273   Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K

[網絡24] 圓桌問題 ()

sizeof ble har 一個 lan double ace cor cte 洛谷傳送門 LOJ傳送門 這估計是$24$題裏建圖最好想的了吧.. 源點$S$向每個單位連流量為$r_{i}$的邊,每個圓桌向匯點$T$連流量為$c_{i}$的邊,每個單位和每個圓桌之間都

loj 1154(+列舉匯點)

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include&l

題解 洛谷 P3376 【【模板】網絡

line 效率 tro 什麽 struct while utc 有一個 putc 本人很弱,只會Dinic、EK與Ford-Fulkerson...(正在學習ISAP...) 這裏講Dinic... Dinic:與Ford-Fulkerson和的思路相似(話說好像最大流

【BZOJ1458】士兵占領 模板

gis deep getch pac etc getchar() style efi %d 我們只要把他們可以有的限制用流量限制,再用兩者關系限制一下就可以開心的跑了。 #include <cstdio> #include <cstring> #i

Minimum Cost POJ - 2516 (模板 spfa小費用

edge 題意 include spf while add define 模板 觀察 題意: 人回家,一步一塊錢,有x個人,y個房子,求能回家的最大人數且使之費用最小 解析: 就是。。。。套模板,,,, 建圖(⊙﹏⊙)。。。要仔細觀察吶 對於人拆不拆都可以 都能過,,,,

洛谷 P3128 [USACO15DEC]Max Flow-樹上差分(點權)(模板)

因為徐州現場賽的G是樹上差分+組合數學,但是比賽的時候沒有寫出來(自閉),背鍋。 會差分陣列但是不會樹上差分,然後就學了一下。 看了一些東西之後,對樹上差分寫一點個人的理解:   首先要知道在樹上,兩點之間只有一條路徑。樹上差分就是在樹上用差分陣列,因為是在樹上的操作,所以要用到lca,因為

婚車1667(模板

題目描述 航哥是個土豪,他想在讓城市佈滿他的婚車。但是城市的每條道路單位時間能通過的婚車是有限的,超出則會造成擁堵。他在1號點屯了足夠數量的車子,他想知道從城市1號點派出婚車去n號點迎接新娘,在買通交警只允許他的婚車在車道上行駛的條件下,足夠多時間之後,n號點單位時間內最多能容納多少量婚車。 輸

模板 EdmondsKarp】HDU

Problem Description 給你m,n分別代表m條邊,n個點。接下來給你m條邊,每條邊u,v,w。u->v流量的容量為w。有重邊 思路:模板題,所以給幾個模板 時間複雜度O(F*|E|),F 為最大流量,E 為邊的個數 Edmon

【網路】POJ1273-Drainage Ditche【模板

這是一道網路流的入門題,用來理解最大流很好。 #include<iostream> #include<string> #include<cstdio> #include<cstring> #include<map&g

poj1273-----基礎(簡單的!--模板

題意:下雨的時候約翰的田裡總是積水,積水把他種的三葉草給淹了,他於是做了若干排水溝,每條溝在起始處安置一個閥門來控制這條溝的最大排水量,現在給出溝的條數以及閥門的個數。並給出每條溝的最大排水量。約翰的田裡的積水處是閥門1,排出水的位置是最後一個閥門。求約翰在處理積水時的最大

(POJ3308)Paratroopers 小割,建圖,模板

Paratroopers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8373 Accept

模板小費用(增廣路)(模板:洛谷P3381)

題目描述 如題,給出一個網路圖,以及其源點和匯點,每條邊已知其最大流量和單位流量費用,求出其網路最大流和在最大流情況下的最小費用。 輸入輸出格式 輸入格式: 第一行包含四個正整數N、M、S、T,分別表示點的個數、有向邊的個數、源點序號、匯點序號。 接下來M行每行包