最小费用最大流
题目描述
如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。
输入格式
第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。
输出格式
一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。
思路
求出一条最小费用边,然后对这条边增广,重复上述过程,直到没有到汇点的边流
求最小费用边,用spfa()
code
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define int long long
const int inf = 0x3f3f3f3f;
const int maxn = 1000;
const int M = 1e9+7;
int n,m,s,t;
struct node
{
int to,cost,dis,next;
}a[2000]; //边数
int head[maxn],cnt = 2;
void ad(int u,int v,int w,int f)
{
a[cnt].to = v;a[cnt].cost = w;a[cnt].dis = f;
a[cnt].next = head[u];head[u] = cnt;cnt++;
}
void add(int u,int v,int w,int f) //建图
{
ad(u,v,w,f);ad(v,u,0,-f);
}
int dis[maxn];
bool vis[maxn];
int pre[maxn]; //前驱
int incf[maxn]; //当前路上的最小流
bool spfa()
{
mem(dis,inf);mem(vis,0);
dis[s] = 0;incf[s] = inf;
queue<int> q;q.push(s);
while(!q.empty())
{
int u = q.front();q.pop();vis[u] = 0;
for(int i = head[u];i; i = a[i].next)
{
if(!a[i].cost) continue;
int v = a[i].to;
if(dis[v] > dis[u]+a[i].dis)
{
dis[v] = dis[u]+a[i].dis;
incf[v] = min(incf[u],a[i].cost);
pre[v] = i;
if(!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
if(dis[t] < inf) return 1;
return 0;
}
int maxflow,mincost;
vector<int> vt;
void mcff()
{
while (spfa())
{
maxflow += incf[t];
mincost += dis[t]*incf[t];
vt.push_back(dis[t]*incf[t]);
int x = t;
while(x != s)
{
int i = pre[x];
a[i].cost -= incf[t];
a[i^1].cost += incf[t];
x = a[i^1].to;
}
}
}