基于贪心选择最小费用增广路增广的算法
Spfa费用流
struct E
{
int to,next,cap,flow,cost;
}edge[maxm];
int head[maxn],tol;
inline void Addedge(int u,int v,int w,int c)
{
edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;edge[tol].cost=c;
edge[tol].next=head[u];head[u]=tol++;
edge[tol].to=u;edge[tol].cap=edge[tol].flow=0;edge[tol].cost=-c;
edge[tol].next=head[v];head[v]=tol++;
return;
}
struct Spfaflow
{
int d[maxn],cur[maxn],s,t,n;
bool vis[maxn];
queue<int>Q;
inline void init(){memset(head,-1,sizeof(head));tol=0;}
inline bool spfa()
{
memset(d,0x3f,sizeof(int)*n);
memset(vis,0,sizeof(bool)*n);
d[s]=0;
Q.push(s);
while(!Q.empty()){
int u=Q.front();Q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&d[v]>d[u]+edge[i].cost){
d[v]=d[u]+edge[i].cost;
if(!vis[v]){
vis[v]=1;
Q.push(v);
}
}
}
}
return d[t]!=INF;
}
inline int dfs(int u,int a)
{
if(u==t) return a;
int f=0;
vis[u]=1;
for(int &i=cur[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]&&edge[i].cap>edge[i].flow&&d[v]==d[u]+edge[i].cost){
int tmp=dfs(v,min(a,edge[i].cap-edge[i].flow));
if(tmp){
edge[i].flow+=tmp;
edge[i^1].flow-=tmp;
f+=tmp;
a-=tmp;
if(!a) break;
}
}
}
return f;
}
inline int Maxflow(int s,int t,int n,int&cost)
{
this->s=s,this->t=t,this->n=n;
int ans=0;
while(spfa()){
memcpy(cur,head,sizeof(int)*n);
while(1){
memset(vis,0,sizeof(bool)*n);
int tmp=dfs(s,INF);
if(!tmp) break;
ans+=tmp;
cost+=tmp*d[t];
}
}
return ans;
}
};
Dijkstra费用流
给每个结点加一个势函数,变换边权为非负,每次更新势函数
struct E
{
int to,next,cap,flow,cost;
}edge[maxm];
int head[maxn],tol;
inline void Addedge(int u,int v,int w,int c)
{
edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;edge[tol].cost=c;
edge[tol].next=head[u];head[u]=tol++;
edge[tol].to=u;edge[tol].cap=edge[tol].flow=0;edge[tol].cost=-c;
edge[tol].next=head[v];head[v]=tol++;
return;
}
struct Dijkstraflow
{
struct Node
{
int u,d;
Node(int x,int y):u(x),d(y){}
bool operator<(const Node&P)const
{
return d>P.d;
}
};
priority_queue<Node>Q;
int d[maxn],h[maxn],pre[maxn],n;
bool vis[maxn];
inline void init(){memset(head,-1,sizeof(head));tol=0;}
inline bool dijkstra(int s,int t)
{
memset(d,0x3f,sizeof(int)*n);
memset(vis,0,sizeof(bool)*n);
pre[s]=-1;
Q.push(Node(s,d[s]=0));
while(!Q.empty()){
int u=Q.top().u;Q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]&&edge[i].cap>edge[i].flow&&d[v]>d[u]+h[u]-h[v]+edge[i].cost){
pre[v]=i;
d[v]=d[u]+h[u]-h[v]+edge[i].cost;
Q.push(Node(v,d[v]));
}
}
}
return d[t]<INF;
}
inline int Maxflow(int s,int t,int n,int &cost)
{
this->n=n;
int ans=0;
memset(h,0,sizeof(int)*n);
while(dijkstra(s,t)){
int Min=INF;
for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
if(Min>edge[i].cap-edge[i].flow){
Min=edge[i].cap-edge[i].flow;
}
}
for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
edge[i].flow+=Min;
edge[i^1].flow-=Min;
}
for(int i=0;i<n;i++) h[i]+=d[i];
ans+=Min;
cost+=Min*h[t];
}
return ans;
}
};
时间复杂度:O(FElogV)
ZKW费用流
适用于流量大,费用小,增广路径短的图,每次至少增加一条可行边
struct E
{
int to,next,cap,flow,cost;
}edge[maxm];
int head[maxn],tol;
inline void Addedge(int u,int v,int w,int c)
{
edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;edge[tol].cost=c;
edge[tol].next=head[u];head[u]=tol++;
edge[tol].to=u;edge[tol].cap=edge[tol].flow=0;edge[tol].cost=-c;
edge[tol].next=head[v];head[v]=tol++;
return;
}
struct Zkwflow
{
int d[maxn],cur[maxn],t,n;
bool vis[maxn];
inline void init(){memset(head,-1,sizeof(head));tol=0;}
inline int dfs(int u,int a)
{
if(u==t) return a;
vis[u]=1;
for(int &i=cur[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]&&edge[i].cap>edge[i].flow&&d[v]==d[u]+edge[i].cost){
int tmp=dfs(v,min(a,edge[i].cap-edge[i].flow));
if(tmp){
edge[i].flow+=tmp;
edge[i^1].flow-=tmp;
return tmp;
}
}
}
return 0;
}
inline bool mdf()
{
int Min=INF;
for(int u=0;u<n;u++){
if(!vis[u]) continue;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&!vis[v]&&Min>d[u]-d[v]+edge[i].cost){
Min=d[u]-d[v]+edge[i].cost;
}
}
}
if(Min==INF) return 0;
for(int i=0;i<n;i++){
if(vis[i]) d[i]-=Min;
}
return 1;
}
inline int Maxflow(int s,int t,int n,int &cost)
{
this->t=t,this->n=n;
memset(d,0,sizeof(int)*n);
int ans=0;
do{
memcpy(cur,head,sizeof(int)*n);
while(1){
memset(vis,0,sizeof(bool)*n);
int tmp=dfs(s,INF);
if(!tmp) break;
ans+=tmp;
cost+=-d[s]*tmp;
}
}while(mdf());
return ans;
}
};