最小费用最大流板子
整理一下自己的板子。详细的思路过程,也不太记得了,有空的话再回过头记录把。
//spfa法 #include<cstdio> #include<queue> #include<algorithm> #include<cstring> using namespace std; const int N=5118,M=51108,inf=0x3f3f3f3f; struct Side{ int v,ne,w,val; }S[2*M]; int s,t,sn,head[N],dis[N],vis[N],flow[N],lu[N]; void init(int n){ sn=0; for(int i=0;i<=n;i++) head[i]=-1; } void add(int u,int v,int w,int val){ S[sn].w=w; S[sn].v=v; S[sn].val=val; S[sn].ne=head[u]; head[u]=sn++; } void addE(int u,int v,int w,int val){ add(u,v,w,val);add(v,u,0,-val); } bool spfa(int n){ queue<int> q; for(int i=0;i<=n;i++){ dis[i]=inf; vis[i]=0; flow[i]=inf; lu[i]=-1; } dis[s]=0; vis[s]=1; q.push(s); while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=S[i].ne){ int v=S[i].v; if(S[i].w>0&&dis[v]>dis[u]+S[i].val){ lu[v]=i; dis[v]=dis[u]+S[i].val; flow[v]=min(flow[u],S[i].w); if(!vis[v]){ vis[v]=1; q.push(v); } } } } return dis[t]!=inf; } void mfml(int n){ int ans=0,ansc=0; while(spfa(n)){ ans+=flow[t]; ansc+=flow[t]*dis[t]; for(int i=lu[t];i!=-1;i=lu[S[i^1].v]){ S[i].w-=flow[t]; S[i^1].w+=flow[t]; } } printf("%d %d\n",ans,ansc); } int main(){ int n,m,u,v,w,val; scanf("%d%d%d%d",&n,&m,&s,&t); init(n); while(m--){ scanf("%d%d%d%d",&u,&v,&w,&val); addE(u,v,w,val); } mfml(n); return 0; }
//zwk费用流 #include<cstdio> #include<queue> #include<algorithm> #include<cstring> using namespace std; const int N=5118,M=51108,inf=1e9+7; struct Side{ int v,ne,w,val; }S[M<<1]; bool vis[N]; int sb,se,sn,ans,ansc,head[N],dis[N],cur[N]; void init(int n){ sn=0; for(int i=0;i<=n;i++) head[i]=-1; } void add(int u,int v,int w,int val){ S[sn].w=w;S[sn].val=val; S[sn].v=v;S[sn].ne=head[u]; head[u]=sn++; } void addE(int u,int v,int w,int val){ add(u,v,w,val);add(v,u,0,-val); } bool spfa(int n){ for(int i=0;i<=n;i++){ dis[i]=inf; vis[i]=false; } dis[se]=0; vis[se]=true; deque<int> q; q.push_back(se); while(!q.empty()){ int u=q.front(); q.pop_front(); vis[u]=false; for(int i=head[u],v;~i;i=S[i].ne){ v=S[i].v; if(S[i^1].w>0&&dis[v]>dis[u]-S[i].val){ dis[v]=dis[u]-S[i].val; if(!vis[v]){ vis[v]=true; if(!q.empty()&&dis[v]<dis[q.front()]) q.push_front(v); else q.push_back(v); } } } } return dis[sb]!=inf; } int dfs(int u,int minf){ if(u==se){ vis[se]=true; return minf; } vis[u]=true; int flow=0,temp,v; for(int &i=cur[u];~i;i=S[i].ne){ v=S[i].v; if(!vis[v]&&S[i].w>0&&dis[v]==dis[u]-S[i].val){ temp=dfs(v,min(S[i].w,minf-flow)); if(temp){ S[i].w-=temp; S[i^1].w+=temp; flow+=temp; ansc+=S[i].val*temp; } if(flow==minf) break; } } return flow; } void mfml(int n){ ans=ansc=0; while(spfa(n)){ do{ for(int i=0;i<=n;i++) vis[i]=false,cur[i]=head[i]; ans+=dfs(sb,inf); }while(vis[se]); } printf("%d %d\n",ans,ansc); } int main(){ int n,m,u,v,w,val; scanf("%d%d%d%d",&n,&m,&sb,&se); init(n); while(m--){ scanf("%d%d%d%d",&u,&v,&w,&val); addE(u,v,w,val); } mfml(n); return 0; }
//dijk费用流 #include<cstdio> #include<queue> #include<algorithm> #include<cstring> using namespace std; const int N=5118,M=51108,inf=1e9+7; struct Side{ int v,ne,w,val; Side(){} Side(int v,int val):v(v),val(val){} bool operator<(const Side &s1)const{ return val>s1.val; } }S[M<<1]; bool vis[N]; int n,sb,se,sn,ansc,head[N],dis[N],flow[N],lu[N],h[N]; void init(int n){ sn=0; for(int i=0;i<=n;i++) head[i]=-1; } void add(int u,int v,int w,int val){ S[sn].w=w;S[sn].val=val; S[sn].v=v;S[sn].ne=head[u]; head[u]=sn++; } void addE(int u,int v,int w,int val){ add(u,v,w,val);add(v,u,0,-val); } bool dijk(){ priority_queue<Side> q; for(int i=0;i<=n;i++){ lu[i]=-1; dis[i]=flow[i]=inf; } dis[sb]=0; q.push(Side(sb,dis[sb])); while(!q.empty()){ int u=q.top().v,w=q.top().val;q.pop(); if(dis[u]<w) continue; for(int i=head[u];~i;i=S[i].ne){ int v=S[i].v; if(S[i].w>0&&dis[v]>dis[u]+S[i].val+h[u]-h[v]){ lu[v]=i; dis[v]=dis[u]+S[i].val+h[u]-h[v]; flow[v]=min(flow[u],S[i].w); q.push(Side(v,dis[v])); } } } return dis[se]!=inf; } int mfml(){ int ans=0,ansc=0; for(int i=0;i<=n;i++) h[i]=0; while(dijk()){ ans+=flow[se]; ansc+=flow[se]*(dis[se]+h[se]-h[sb]); for(int i=lu[se];~i;i=lu[S[i^1].v]){ S[i].w-=flow[se]; S[i^1].w+=flow[se]; } for(int i=0;i<=n;i++) h[i]+=dis[i]; } printf("%d %d\n",ans,ansc); return 0; } int main(){ int m,u,v,w,val; scanf("%d%d%d%d",&n,&m,&sb,&se); init(n); while(m--){ scanf("%d%d%d%d",&u,&v,&w,&val); addE(u,v,w,val); } mfml(); return 0; }
平常题spfa便可以过,毒瘤的时候,可以使用势函数优化的dijkstra版本,zwk费用流在某些数据(稠密图)下是最快的。
我太难了~给个三连吧,亲~~~