[模板]网络最大流 & 最小费用最大流
我的作业部落有学习资料
Dinic 模板
#define rg register #define _ 10001 #define INF 2147483647 #define min(x,y) (x)<(y)?(x):(y) using namespace std; int n,m,s,t,record[_],num_of_edges=-1,cur[_],team[10000001],depth[_]; struct pp { int next,to,w; }edge[(_<<4)+(_<<2)]; inline int read() { rg int save=0,w=1;rg char q=getchar(); while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();} while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar(); return save*w; } inline void add(rg int from,rg int to,rg int ww) { edge[++num_of_edges]=(pp){record[from],to,ww}; record[from]=num_of_edges; } inline bool bfs() { rg int head=0,tail=1; for(rg int i=1;i<=n;++i)depth[i]=0;//depth[]初值为-1,免得返回出发点 depth[s]=1; team[1]=s; do { head++; rg int u=team[head]; for(rg int j=record[u];j!=-1;j=edge[j].next) { rg int to=edge[j].to; if((!depth[to])&&(edge[j].w>0)) { depth[to]=depth[u]+1; team[++tail]=to; if(to==t)return 1; } } }while(head<tail); return 0; } int dfs(rg int u,rg int flow)//找到每条路上的最小残余流量,因此需在回溯时更新每条边的流量 { if(u==t)return flow; for(rg int &j=cur[u]/*当前弧优化*/;j!=-1;j=edge[j].next) { rg int to=edge[j].to; if(depth[to]==depth[u]+1&&(edge[j].w>0)) { rg int D=dfs(to,min(flow,edge[j].w));//到终点的过程中一直在取min if(D>0) { edge[j].w-=D,edge[j^1].w+=D; return D;//每次只找一条可流通路满上(这里就不管现实中物理的联通器原理了) } } } return 0; } inline int Dinic() { rg int i,j,ans=0; while(bfs()) { for(i=1;i<=n;++i)cur[i]=record[i]; while(int now=dfs(s,INF))ans+=now; } return ans; } int main() { n=read(),m=read(),s=read(),t=read(); rg int i,j; for(i=1;i<=n;++i)record[i]=-1; for(i=1;i<=m;++i) { rg int x=read(),y=read(),ww=read(); add(x,y,ww),add(y,x,0); } printf("%d\n",Dinic()); return 0; }
最小费用最大流:
#define rg register #define _ 5001 #define __ 50001 #define INF 2147483647 using namespace std; int n,m,s,t,record[_],num_of_edges=1,pre[_],res_flow,res_cost,dis[_],team[__<<4];//以后num_of_edges都赋为 1 !!! bool exist[_]; struct pp { int next,to,w,cost; }edge[__<<1]; inline int read() { rg int save=0,w=1;rg char q=getchar(); while(q<'0'||q>'9'){if(q=='-')w=-1;q=getchar();} while(q>='0'&&q<='9')save=(save<<3)+(save<<1)+q-'0',q=getchar(); return w*save; } inline void add(rg int from,rg int to,rg int ww,rg int f) { edge[++num_of_edges]=(pp){record[from],to,ww,f}; record[from]=num_of_edges; } inline bool SPFA() { rg int head=0,tail=1; for(rg int i=1;i<=n;++i)exist[i]=0,dis[i]=INF; dis[s]=0; team[1]=s; do { head++; rg int i=team[head]; exist[i]=0; for(rg int j=record[i];j;j=edge[j].next) { rg int to=edge[j].to; if(edge[j].w>0&&dis[to]>dis[i]+edge[j].cost) { dis[to]=dis[i]+edge[j].cost; pre[to]=j; if(!exist[to])team[++tail]=to,exist[to]=1; } } }while(head<tail); return dis[t]!=INF; } inline void doit() { while(SPFA()) { rg int flow=INF; for(rg int i=pre[t];i;i=pre[edge[i^1].to]) flow=min(flow,edge[i].w); res_flow+=flow; res_cost+=dis[t]*flow; for(rg int i=pre[t];i;i=pre[edge[i^1].to]) edge[i].w-=flow,edge[i^1].w+=flow; } printf("%d %d\n",res_flow,res_cost); } int main() { n=read(),m=read(),s=read(),t=read(); rg int i,j; for(i=1;i<=m;++i) { rg int u=read(),v=read(),w=read(),f=read(); add(u,v,w,f),add(v,u,0,-f); } doit();//实在不想用那个MCMF() return 0; }