最小費用最大流
步驟:
1.spfa()找最小費用的路徑,並記錄;
2.利用最大流維護路徑;
模板題:洛谷P3381
#include <bits/stdc++.h>
using namespace std;
const int N=5020;
const int maxn=1e5+55;
const int inf=0x3f3f3f3f;
int dis[N],head[maxn],pre[N],f[N]; //dis[]記錄最小花費,pre[]記錄節點值,f[]記錄路徑最小流量;
int cnt=0,s,t,max_flow=0,min_cost=0;
struct node{ //鏈式向前星建邊;
int u,to,next,cost,flow;
}mp[maxn];
inline void add(int x, int y, int cost,int val)
{
mp[cnt].u=x;
mp[cnt].to=y;
mp[cnt].cost=cost;
mp[cnt].flow=val;
mp[cnt].next=head[x];
head[x]=cnt++;
}
int spfa() //跑spfa,找到滿足條件的最小化費;
{
bool p[N];
for(int i=0;i<N;++i)
{
p[i]=false;
dis[i]=inf;
pre[i]=-1;
}
queue<int >q;
q.push(s);
dis[s]=0;
f[s]=inf;
while(!q.empty()){
int u=q.front();
q.pop();
p[u]=false;
for(int i=head[u];~i;i=mp[i].next){
int to=mp[i].to;
int cost=mp[i].cost;
int flow=mp[i].flow;
if(flow>0&&dis[to]>dis[u]+cost){
dis[to]=dis[u]+cost;
f[to]=min(f[u],flow); //找路徑最小流量;
pre[to]=i; //記錄節點的值,用於後面的維護路徑流量;
if(!p[to]){
p[to]=true;
q.push(to);
}
}
}
}
return pre[t];
}
void EK()
{
while(spfa()!=-1){
int now=t,las=pre[now];
while(s^now){ //回溯路徑,維護流量;
mp[las].flow-=f[t];
mp[las^1].flow+=f[t];
now=mp[las].u;
las=pre[now];
}
min_cost+=f[t]*dis[t];
max_flow+=f[t];
}
}
int main()
{
int n,m,x,y,cost,val;
memset(head,-1,sizeof(head));
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=0;i<m;++i){
scanf("%d%d%d%d",&x,&y,&val,&cost);
add(x,y,cost,val); //建邊;
add(y,x,-cost,0);
}
EK();
printf("%d %d\n",max_flow,min_cost);
return 0;
}