没有啥笔记 只有一份代码 反正最大流弄熟了这个肯定看得懂
这个是EK spfa实现
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
int n,m,s,t,tot,pre[5005],zdl[5005],inflow[5005],max_flow,min_spend,first[5005];
bool inque[5005];
struct Edge
{
int to;
int spend;
int flow;
int cap;
int next;
}edge[100005];
inline void init()
{
memset(first,-1,sizeof(first));
for(int i=0;i<=50004;i++) edge[i].next=-1;
}
inline void add_edge(int u,int v,int w,int f,int flow)
{
edge[tot].to=v;
edge[tot].next=first[u];
edge[tot].flow=flow;
edge[tot].cap=w;
edge[tot].spend=f;
first[u]=tot++; //注意tot放的地方 只有数组下标从0开始才能用^1求方向边
}
inline bool spfa(int s,int t)
{
queue<int> q;
memset(inque,false,sizeof(inque));
memset(pre,0,sizeof(pre));
memset(zdl,INF,sizeof(zdl));//两个初始值勿忘
q.push(s);
inque[s]=true;
inflow[s]=INF; //inflow:即到达当前点的流量
zdl[s]=0;
while(!q.empty())
{
int now=q.front();
inque[now]=false;
q.pop();
for(int u=first[now];u!=-1;u=edge[u].next)
{
int vis=edge[u].to;
//如果当前边还可以流且最短路可以更新
if(edge[u].cap-edge[u].flow>0&&zdl[now]+edge[u].spend<zdl[vis])
{
zdl[vis]=zdl[now]+edge[u].spend;
pre[vis]=u; //前驱
inflow[vis]=min(inflow[now],edge[u].cap-edge[u].flow); //常规的更新操作 会最大流的应该都会吧
if(!inque[vis])
{
q.push(vis);
inque[vis]=true;
}
}
}
}
return zdl[t]!=INF;
}
inline void update(int s,int t)
{
int x=t;
while(x!=s)
{
int i=pre[x];
edge[i].flow+=inflow[t]; //更新操作
edge[i^1].flow-=inflow[t];
x=edge[i^1].to;
}
max_flow+=inflow[t];
min_spend+=zdl[t]*inflow[t];
}
void edmonds_karp(int s,int t)
{
while(spfa(s,t)) //持续从s向t寻找一条单位费用之和最小的增广路
{
update(s,t);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);//增加cin速度的
init(); //初始first,next=-1
cin>>n>>m>>s>>t;
for(int i=1;i<=m;i++)
{
int u,v,w,f;
cin>>u>>v>>w>>f;
add_edge(u,v,w,f,0);
add_edge(v,u,w,-f,w); //反向边费用为负
}
edmonds_karp(s,t);
cout<<max_flow<<" "<<min_spend<<endl;
return 0;
}
实质和最大流的几个算法差不多.....最小费用最大流就是在每次找到最短路(权值为费用)过后 加上最短路到汇点的距离*流就行了..