ZKW费用流+SPFA SLF优化,简直针快!
说几个关键点
对于普通费用流,因为每次增广后有一些边会因流量为0而导致一些点的最短路增大,但没有必要再跑一遍spfa.
...
其实具体我也不知道怎么弄得 毕竟我只是一个背板选手
#include<bits/stdc++.h>
#define re register
const int N=405;
const int M=15005;
const int INF=0x3f3f3f3f;
using namespace std;
template <class T>
inline void read(T &x)
{
x=0;
static char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
}
struct Edge
{
int to,next,f,cap;
}edge[2*M];
int n,m,s,t;
int tot=1,first[N];
inline void addedge(int u,int v,int w,int f)
{
tot++;
edge[tot].to=v; edge[tot].cap=w; edge[tot].next=first[u]; edge[tot].f=f; first[u]=tot;
}
int dis[N];
bool inque[N];
inline bool spfa()
{
memset(inque,0,sizeof(inque));
memset(dis,0x3f,sizeof(dis));
deque <int> q;
dis[t]=0; q.push_front(t); inque[t]=1;
while(!q.empty())
{
int now=q.front(); q.pop_front(); inque[now]=0;
for(re int u=first[now];u;u=edge[u].next)
{
int vis=edge[u].to;
if(edge[u^1].cap&&dis[now]-edge[u].f<dis[vis])
{
dis[vis]=dis[now]-edge[u].f;
if(!inque[vis])
{
inque[vis]=1;
if(!q.empty()&&dis[vis]<dis[q.front()]) q.push_front(vis);
else q.push_back(vis);
}
}
}
}
return dis[s]<INF;
}
bool V[N];
int ans=0;
int dfs(int now,int f)
{
V[now]=1;
if(!f||now==t) return f;
int out=0;
for(re int u=first[now];u;u=edge[u].next)
{
int vis=edge[u].to;
if(!V[vis]&&edge[u].cap&&dis[now]-edge[u].f==dis[vis])
{
int w=dfs(vis,min(f,edge[u].cap));
if(!w) continue;
ans+=w*edge[u].f; edge[u].cap-=w; edge[u^1].cap+=w; f-=w; out+=w;
if(!f) break;
}
}
return out;
}
void zkwflow()
{
int maxflow=0;
while(spfa())
{
V[t]=1;
while(V[t])
{
memset(V,0,sizeof(V));
maxflow+=dfs(s,INF);
}
}
cout<<maxflow<<" ";
}
int main()
{
cin>>n>>m;
int u,v,c,f;
for(re int i=1;i<=m;i++)
{
read(u); read(v); read(c); read(f);
addedge(u,v,c,f); addedge(v,u,0,-f);
}
s=1; t=n;
zkwflow();
cout<<ans;
return 0;
}