费用流学习笔记
费用流就是在最大流的基础上,每条边每单位流量有一个费用,求最大流的基础上费用最小。
其实非常简单,就是在求最大流时,增广路时使用spfa算法,求助费用和最小的增广路。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int inf=1e9;
int n,m,s,t;
struct edge{
int v,nx,w,c;
}e[100005];
int cnt,hd[5005];
void add(int u,int v,int w,int c){
e[++cnt]=edge{v,hd[u],w,c};
hd[u]=cnt;
}
int dis[100005],flow[100005],pre[1000005];
bool vis[100005];
bool spfa(){
queue<int> q;q.push(s);
memset(dis,0x3f,sizeof(dis));memset(flow,0,sizeof(flow));memset(vis,0,sizeof(vis));
dis[s]=0;flow[s]=inf;
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=0;
for(int i=hd[u];i;i=e[i].nx){
int v=e[i].v;if(e[i].w<=0 || dis[v]<=dis[u]+e[i].c)continue;
dis[v]=dis[u]+e[i].c;flow[v]=min(flow[u],e[i].w);pre[v]=i;
if(!vis[v])vis[v]=1,q.push(v);
}
}
return dis[t]!=0x3f3f3f3f;
}
inline int id(int i){
if(i&1)return i+1;
else return i-1;
}
void work(){
ll res=0,sum=0;
while(spfa()){
// printf("%d %d\n",flow[t],dis[t]);
res+=flow[t];sum+=dis[t]*flow[t];
int u=t;
while(u!=s){
// printf("%d\n",u);
int i=pre[u];
e[i].w-=flow[t];e[id(i)].w+=flow[t];
u=e[id(i)].v;
}
}
printf("%lld %lld\n",res,sum);
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++){
int u,v,w,c;scanf("%d%d%d%d",&u,&v,&w,&c);
add(u,v,w,c);add(v,u,0,-c);
}
work();
return 0;
}
本文作者:kent
本文链接:https://www.cnblogs.com/kentsbk/p/18043152
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步