P3381【模板】最小费用最大流

题目

题目

思路

显然,Dinic不适合解决费用流问题,因为它进行分层式的优化,其实我们去掉这重优化就是EK算法。
接下来,使用EK算法也不能解决费用流,但是我们可以把bfs替换为spfa,使用spfa来判断增广路是否存在,因为EK算法的思路有一个撤销的理念,所以我们可以用spfa求一条单价最小的增广路,然后把增广路加上去(一种贪心),因为可以撤销,所以这就是可撤销贪心的思路。
code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
int n,m,s,t,x,y,tot=2,head[5001],dep[5001],ans2,fy;
bool book[5001];
long long w,ans,in[5001];
long long mn(long long x,long long y)
{
    
    
 return (x>y?y:x);
}
struct f{
    
    
 int to,net;
 long long w,fy;
} a[100011];
int b[100011];
void add(int x,int y,long long w,long long fy)
{
    
    
 a[tot].to=y,a[tot].w=w,a[tot].net=head[x],a[tot].fy=fy,head[x]=tot++;
 return;
}
bool spfa()
{
    
    
 memset(dep,0x3f,sizeof(dep));
 memset(book,0,sizeof(book));
 queue<int> u;
 u.push(s);
 book[s]=1,dep[s]=0,in[s]=0x7fffffff;
 while (u.size())
 {
    
    
  y=u.front();
  u.pop();
  book[y]=0;
  for (int j=head[y];j;j=a[j].net)
  {
    
    
   if (a[j].w!=0&&dep[y]+a[j].fy<dep[a[j].to])
   {
    
    
    dep[a[j].to]=dep[y]+a[j].fy;//记录单价和 
    in[a[j].to]=min(in[y],a[j].w);
    b[a[j].to]=j;
    if (!book[a[j].to]) book[a[j].to]=1,u.push(a[j].to);
   }
  }
 }
 return dep[t]!=1061109567;
}
void dfs()
{
    
    
 x=t;
 ans+=in[t];
 ans2+=dep[t]*in[t];
 while (x!=s)
 {
    
    
  a[b[x]].w-=in[t],a[b[x]^1].w+=in[t],x=a[b[x]^1].to; 
 }//清空增广路 
 return;
}
int main()
{
    
    
 scanf("%d%d%d%d",&n,&m,&s,&t);
 for (int i=0;i<m;i++)
 {
    
    
  scanf("%d%d%lld%lld",&x,&y,&w,&fy);
  add(x,y,w,fy);
  add(y,x,0,-fy);
 }
 while (spfa())
 {
    
    
  dfs();
 }
 cout<<ans<<' '<<ans2;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_49843717/article/details/114333379
今日推荐