题目链接:https://loj.ac/problem/127
最大流hlpp模板(原作者是xehoth,我就改了改拿来用用)
请根据题目要求做修改。
Note:可将vector改为链式前向星,代码我就不贴出来了,如有需要请私信我。
update(2018.9.29):
算是对这个板子的总结。
在检验板子的时候发现这个东西跑网络流时间下限较高,但上限小,适合跑边数多的图,毕竟O(),时间也很稳定,对于一些随机图而言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;
}