【洛谷 P3381】最小费用最大流(SPFA+EK)

在最大流的基础上把BFS换成SPFA即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100050;
const int INF = 0x3f3f3f3f;
int head[maxn];
bool vis[maxn];
int dis[maxn];
int flow[maxn];
int n,m,s,t;
struct edge{
	int v,f,c,next;
}e[maxn];
struct node{
	int id;
	int v;
}pre[maxn];
int cnt;
void init(){
	cnt=0;
	memset(head,-1,sizeof(head));
	memset(vis,0,sizeof(vis));
}
void addedge(int u,int v,int f,int c){
	e[cnt].v=v;
	e[cnt].f=f;
	e[cnt].c=c;
	e[cnt].next=head[u];
	head[u]=cnt++;
}
bool spfa()
{
    memset(dis,INF,sizeof(dis));
    memset(vis,0,sizeof(vis));
    memset(flow,INF,sizeof(flow));
    queue<int>que;
    que.push(s);dis[s]=0;
    while(!que.empty())
    {
        int u=que.front();que.pop();
        vis[u]=0;
        for(int i=head[u];i+1;i=e[i].next)
        {
            int v=e[i].v,di=e[i].c,c=e[i].f;
            if(c&&dis[v]>dis[u]+di)
            {
                dis[v]=dis[u]+di;
                pre[v].id=i;
                pre[v].v=u;//存v点的父亲u
                flow[v]=min(c,flow[u]);
                if(!vis[v])
                {
                    que.push(v);vis[v]=1;
                }
            }
        }
    }
    return flow[t]!=flow[s];
}
void MCMF()
{
	int mf=0;
	int mc=0;
    while(spfa())
    {
        mf+=flow[t];//更新最大流
        mc+=flow[t]*dis[t];//更新最小费用
        for(int u=t;u!=s;u=pre[u].v)//从T返回沿路径修改剩余容量
        {
            int v=pre[u].id;
            e[v].f-=flow[t];//正边减掉增广量
            e[v^1].f+=flow[t];//反边减掉增广量
        }
    }
    printf("%d %d\n",mf,mc);
}
int main(){
	init();
	cin>>n>>m>>s>>t;
	int u,v,f,c;
	for(int i=1;i<=m;i++){
		cin>>u>>v>>f>>c;
		addedge(u,v,f,c);
		addedge(v,u,0,-c);
	}
	MCMF();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/duanghaha/article/details/82992236
今日推荐