P4722 【模板】最大流 加强版 / 预流推进

P4722 【模板】最大流 加强版 / 预流推进在这里插入图片描述

抄一下马哥板子啦:
自己也不理解,太垃圾了,只能抄马哥板子。
马哥的板子也T了,可能是我脸太黑。。
然后就去抄了个板子。。。这真的是抄的。。。
一点也看不懂。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<list>
#define ll long long
#define llu unsigned ll
#define pb push_back
#define pr make_pair
using namespace std;


char buffer[100001],*S,*T;
inline char Get_Char()
{
    if (S==T)
    {
        T=(S=buffer)+fread(buffer,1,100001,stdin);
        if (S==T) return EOF;
    }
    return *S++;
}
inline int read()
{
    char c;int re=0;
    for(c=Get_Char();c<'0'||c>'9';c=Get_Char());
    while(c>='0'&&c<='9') re=re*10+(c-'0'),c=Get_Char();
    return re;
}


const int inf=0x7fffffff;//本题最大流上限较大
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int maxn=1210;
const int maxm=120100;

struct node
{
    int n,m,s,t,hst,nwh;
    //指明 n 点数,m 边数,s 起点,t 终点
    vector<int>lft,gap,ht,q,mlst[maxn];
    struct edge
    {
        int ver,flw,nt;
        edge(int _ver,int _flw,int _nt)
        {
            ver=_ver,flw=_flw,nt=_nt;
        }
    };
    vector<edge>head[maxn];
    list<int>lst[maxn];
    vector<list<int>::iterator>it;


    #define eachHead(x) for(std::vector<edge>::iterator p=head[x].begin();p!=head[x].end();++p)
    #define eachList(x) for(std::list<int>::iterator p=lst[x].begin();p!=lst[x].end();++p)

    void add(void)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        head[x].pb(edge(y,z,head[y].size()));
        head[y].pb(edge(x,0,head[x].size()-1));
    }

    void rlb(void)
    {
        ht.assign(n+3,n);gap.assign(n+3,0);ht[t]=0;
        q.clear();q.resize(n+3);
        int l=0,r=0,x;
        for(q[r++]=t;l<r;)
        {
            x=q[l++];
            eachHead(x)
            {
                if(ht[p->ver]==n&&head[p->ver][p->nt].flw)
                    ++gap[ht[p->ver]=ht[x]+1],q[r++]=p->ver;
            }
        }
        for(int i=1;i<=n;i++) mlst[i].clear(),lst[i].clear();
        for(int i=1;i<=n;i++)
        {
            if(ht[i]<n)
            {
                it[i]=lst[ht[i]].insert(lst[ht[i]].begin(),i);
                if(lft[i]>0) mlst[ht[i]].pb(i);
            }
        }
        hst=(nwh=ht[q[r-1]]);
    }

    void psh(int x,edge &e)
    {
        int y=e.ver,df=min(lft[x],e.flw);
        e.flw-=df,head[y][e.nt].flw+=df;
        lft[x]-=df,lft[y]+=df;
        if(lft[y]>0&&lft[y]<=df) mlst[ht[y]].pb(y);
    }

    void psh(int x)
    {
        int nh=n,htu=ht[x];
        eachHead(x)
        {
            if(p->flw)
            {
                if(ht[x]==ht[p->ver]+1)
                {
                    psh(x,*p);
                    if(lft[x]<=0) return;
                }
                else nh=min(nh,ht[p->ver]+1);
            }
        }
        if(gap[htu]==1)
        {
            for(int i=htu;i<=hst;i++)
            {
                eachList(i) --gap[ht[*p]],ht[*p]=n;
                lst[i].clear();
            }
            hst=htu-1;
        }
        else
        {
            --gap[htu],it[x]=lst[htu].erase(it[x]),ht[x]=nh;
            if(nh==n) return;
            gap[nh]++,it[x]=lst[nh].insert(lst[nh].begin(),x);
            hst=max(hst,nwh=nh),mlst[nh].pb(x);
        }
    }

    int hlpp(void)
    {
        nwh=hst=0,ht.assign(n+3,0),ht[s]=n,it.resize(n+3);
        for(int i=1;i<=n;i++)
        {
            if(i!=s) it[i]=lst[ht[i]].insert(lst[ht[i]].begin(),i);
        }
        gap.assign(n+3,0),gap[0]=n-1,lft.assign(n+3,0),lft[s]=inf,lft[t]=-inf;
        eachHead(s) psh(s,*p);
        rlb();
        for(int x;nwh;)
        {
            if(mlst[nwh].empty()) nwh--;
            else x=mlst[nwh].back(),mlst[nwh].pop_back(),psh(x);
        }
        return lft[t]+inf;
    }
}flow;





int main(void)
{
    scanf("%d%d%d%d",&flow.n,&flow.m,&flow.s,&flow.t);
    for(int i=1;i<=flow.m;i++)
    {
        flow.add();
    }
    printf("%d\n",flow.hlpp());
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值