1. 程式人生 > >【洛谷 P3381】最小費用最大流(SPFA+EK)

【洛谷 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; }