用zkw模板跑了一下,简直吓尿。。。我的spfa模板跑需要3s,zkw模板才要0.1s。。。。。。。。。。差距太大了。。
zkw模板还没来得及学,所以将spfa的模板搬上来吧。。
最小费用最大流,就是每次用最短路算法找出增广路,增广即可。
spfa未优化版本:
#include <cstdio> #include <cstring> #include <queue> using namespace std; #define CC(a, c) memset(a, c, sizeof(a)) #define FOR(i,a,n) for(i=a;i<=n;++i) const int maxn=1000, maxm=1000000, oo=100000000; int cap[maxm], cost[maxm], d[maxn], p[maxn]; int ihead[maxn], inext[maxm], to[maxm], from[maxm], cnt; queue<int> q; int vis[maxn]; int min(const int& a, const int& b) { return a < b ? a : b; } void add(int u, int v, int c, int w) { inext[++cnt]=ihead[u]; ihead[u]=cnt; from[cnt]=u; to[cnt]=v; cap[cnt]=c; cost[cnt]=w; inext[++cnt]=ihead[v]; ihead[v]=cnt; from[cnt]=v; to[cnt]=u; cap[cnt]=0; cost[cnt]=0; } bool spfa(int s, int t, int n) { int i, u; FOR(i, 0, n) d[i]=oo; CC(vis, 0); CC(p, 0); d[s]=0; q.push(s); vis[s]=1; while(!q.empty()) { u=q.front(); q.pop(); for(i=ihead[u]; i; i=inext[i]) if(cap[i]>0 && d[u]+cost[i]<d[to[i]]) { d[to[i]]=d[u]+cost[i]; p[to[i]]=i; if(!vis[to[i]]) { vis[to[i]]=1; q.push(to[i]); } } vis[u]=0; } return d[t]!=oo; } void mincost(int s, int t, int n, int& flow, int& mcost) { int u, f; while(spfa(s, t, n)) { for(u=t, f=oo; u!=s; u=from[p[u]]) f=min(f, cap[p[u]]); flow+=f; mcost+=f*d[t]; for(u=t; u!=s; u=from[p[u]]) { cap[p[u]]-=f; cap[p[u]^1]+=f; cost[p[u]^1]=-cost[p[u]]; //这里要注意,反向弧的代价要等于正向弧的相反数,这样才能退流 } } } void init() { cnt=1; CC(ihead, 0); } int main() { int n, m, u, v, c, w, i; scanf("%d%d", &n, &m); init(); for(i=1; i<=m; ++i) { scanf("%d%d%d%d", &u, &v, &c, &w); add(u, v, c, w); } int flow, mcost; mincost(1, n, n, flow, mcost); printf("%d ", mcost); return 0; }