【模板】最小费用最大流【费用流】
题目大意:
给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。
思路:
既然是模板题,那么数据肯定很水。
我都过了。
费用流其实就是最大流改一个而已,很简单。
代码:
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#define Inf 2147483647
using namespace std;
int n,m,s,t,x,y,c,w,k,minn,ans,sum,dis[10001],head[250011];
bool vis[10001];
struct edge //邻接表
{
int next,to,c,w;
}e[250011];
struct pre //记录路径
{
int fa,e;
}p[250011];
void add(int from,int to,int c,int w) //建模
{
k++;
e[k].to=to;
e[k].c=c;
e[k].w=w;
e[k].next=head[from];
head[from]=k;
}
bool spfa() //最短路不解释
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(p,0,sizeof(p));
queue<int> q;
q.push(s);
vis[s]=1;
dis[s]=0;
while (q.size())
{
int u=q.front();
q.pop();
vis[u]=0;
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if (e[i].c&&dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
p[v].fa=u;
p[v].e=i;
if (!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
return dis[t]!=0x3f3f3f3f;
}
int main()
{
k=1;
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x,&y,&c,&w);
add(x,y,c,w);
add(y,x,0,-w); //反向变的费用为正向边的相反数
}
while (spfa())
{
minn=Inf;
for (int i=t;i!=s;i=p[i].fa)
minn=min(minn,e[p[i].e].c); //求最小流量
for (int i=t;i!=s;i=p[i].fa)
{
e[p[i].e].c-=minn; //正向边
e[p[i].e^1].c+=minn; //反向边
}
ans+=minn; //最大流
sum=sum+minn*dis[t]; //最小花费
}
printf("%d %d\n",ans,sum);
return 0;
}