最小费用流模板
可以计算负权边的dijkstra
//最小费用流Dijkstra算法 //Dijkstra算法求最小费用流核心代码: //h[MAX_V]:导入势保证所有边均为非负边 O(FElogV) int min_cost_flow(int n, int v, int s, int t, int f) { int i, ans = 0; fill(h, h + v, 0); while(f > 0) { //Dijkstra算法:寻找最短路 O(ElogV) priority_queue<P, vector<P>, greater<P> > que; fill(dis, dis + v, INF); dis[0] = 0; que.push(P(0, s)); while(!que.empty()) { P p = que.top(); que.pop(); int v = p.second; if(dis[v] < p.first) continue; int size = G[v].size(); for(i = 0; i < size; ++i) { edge es = G[v][i];//**** if(es.cap > 0 && dis[es.to] > dis[v] + es.cost + h[v] - h[es.to]) { dis[es.to] = dis[v] + es.cost + h[v] - h[es.to]; prevv[es.to] = v; preve[es.to] = i; que.push(P(dis[es.to], es.to)); } } } if(dis[t] == INF) return -1; //更新势 for(i = 0; i < v; ++i) h[i] += dis[i]; int d = f; for(i = t; i != s; i = prevv[i]) d = min(d, G[prevv[i]][preve[i]].cap); ans += d * h[t]; f -= d; for(i = t; i != s; i = prevv[i]) { edge &es = G[prevv[i]][preve[i]]; es.cap -= d; G[i][es.rev].cap += d; } } return ans; }
简单易行但是复杂度不稳定的spfa
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int INF=0x7f7f7f7f; const int MAXN=100000; struct Edge { int u,v,w,c,next;//u起点,v终点,w容量,c花费,next下一条边 }E[MAXN]; int node,head[MAXN]; int pre[MAXN],cost[MAXN],vis[MAXN]; int s,t; int n,m,ans1,ans2; void insert(int u,int v,int w,int c) { E[++node]=(Edge){u,v,w,c,head[u]}; head[u]=node; E[++node]=(Edge){v,u,0,-c,head[v]}; head[v]=node; } bool spfa() { queue<int> Q; memset(cost,0x7f,sizeof(cost)); Q.push(s); cost[s]=0;vis[s]=1; while(!Q.empty()) { int q=Q.front();Q.pop(); for(int i=head[q];i;i=E[i].next) if(E[i].w&&cost[q]+E[i].c<cost[E[i].v]) { cost[E[i].v]=cost[q]+E[i].c; pre[E[i].v]=i; if(!vis[E[i].v]) { Q.push(E[i].v); vis[E[i].v]=1; } } vis[q]=0; } return cost[t]!=INF; } void mcf() { int minn=INF; for(int i=pre[t];i;i=pre[E[i].u]) minn=min(minn,E[i].w); for(int i=pre[t];i;i=pre[E[i].u]) { ans2+=minn*E[i].c; E[i].w-=minn; E[i^1].w+=minn; } ans1+=minn; } int main() { scanf("%d%d%d%d",&n,&m,&s,&t); for(int i=1;i<=m;i++) { int u,v,w,c; scanf("%d%d%d%d",&u,&v,&w,&c); insert(u,v,w,c); } while(spfa()) mcf(); printf("%d %d",ans1,ans2);//ans1最大流 ans2最小费用 return 0; }