思路:
反复用spfa算法做源到汇的最短路进行增广,边权值为边上单位费用。反向边上的单位费用是负的。
直到无法增广,即为找到最小费用最大流。
成立原因:每次增广时,每增加1个流量,所增加的费用都是最小的。
因为有负权边(取消流的时候产生的),所以不能用迪杰斯特拉算法求最短路。
因为增广的时候要知道上个节点,这不难,但还要快速的知道其反向边是哪个,这个就比较麻烦
而如果用邻接矩阵的话又太占空间,所以用邻接表,方法如下:
给每条边编号,一个边和其的反向边放在一起,所以编号为i的边的反向边的编号是i^1
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=1000+5;
const int INF=1000000000;
struct Edge{
int from,to,flow,weight;
Edge(int f,int t,int fl,int w):from(f),to(t),flow(fl),weight(w){}
};
vector<Edge> edges;
vector<vector<int> > G(maxn);
bool inq[maxn]; //判断是否在队列里
int dist[maxn];
int prev[maxn]; //记录路径
void AddEdge(int u,int v,int fl,int w)
{
edges.push_back(Edge(u,v,fl,w));
G[u].push_back(edges.size()-1); //保存该边的编号
}
bool Spfa(int s,int t)
{
memset(inq,false,sizeof(inq));
fill(dist,dist+t+2