最小费用最大流


link

也是一道模板题,和最大流是一个道理。我学的这种写法是Dinic的改进版,给每条边维护两个边权,一个是流量,一个是费用。每次对费用用SPFA跑一个最短路,然后就着这个最短路去跑一次Dinic。唯一需要注意的是反边。考虑到反边的本质是让某条旧路径放弃原有的那一段路不走了,所以费用应该会减少,建边时对应的费用边权赋值为费用的相反数即可。

#include
#include
#include
//#define zczc
using namespace std;
const int N=5010;
const int M=50010;
const int inf=1e9;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline int min(int s1,int s2){
	return s1qu;
bool inq[N],vis[N];
int dis[N],q[N],l,r;
bool check(){
	memset(dis,0x3f,sizeof(dis));
	memset(inq,false,sizeof(inq));
	memset(vis,false,sizeof(vis));
	dis[s]=0;qu.push(s);
	while(!qu.empty()){
		int wh=qu.front();qu.pop();inq[wh]=false;
		for(int i=head[wh],th;i;i=e[i].next){
			if(e[i].v1<=0||dis[wh]+e[i].v2>=dis[th=e[i].t])continue;
			dis[th]=dis[wh]+e[i].v2;if(!inq[th])inq[th]=true,qu.push(th);
		}
	}
	return dis[t]