[洛谷P2604][ZJOI2010]网络扩容
题目大意:给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。
求: 1.在不扩容的情况下,1到N的最大流; 2.将1到N的最大流增加K所需的最小费用。
题解:先跑最大流,在残余网络上跑费用流
卡点:无
C++ Code:
#include<cstdio> #include<cctype> #include<cstring> #define maxn 5010 using namespace std; const int inf=0x3f3f3f3f; int n,m,k; int u[5010],v[5010],w[5010],c[5010]; int d[maxn],pre[maxn]; int q[maxn],h,t; int st=1,ed; int head[maxn],cnt=2; struct Edge{ int to,nxt,w,cost; }e[5010<<2]; bool vis[maxn]; char ch; void read(int &x){ ch=getchar(); while (!isdigit(ch))ch=getchar(); for (x=ch^48,ch=getchar();isdigit(ch);ch=getchar())x=x*10+(ch^48); } inline int min(int a,int b){return a<b?a:b;} void add(int a,int b,int c,int d){ e[cnt]=(Edge){b,head[a],c,d};head[a]=cnt; e[cnt^1]=(Edge){a,head[b],0,-d};head[b]=cnt^1; cnt+=2; } bool bfs(){ memset(d,0,sizeof d); d[q[h=t=1]=st]=1; while (h<=t){ int x=q[h++]; if (x==ed)return true; for (int i=head[x];i;i=e[i].nxt){ int to=e[i].to; if ((!d[to])&&e[i].w){ d[to]=d[x]+1; q[++t]=to; } } } return d[ed]; } int dfs(int x,int low){ if (x==ed||!low)return low; int res=0,w; for (int i=head[x];i;i=e[i].nxt){ int to=e[i].to; if ((d[to]==d[x]+1)&&e[i].w){ w=dfs(to,min(low-res,e[i].w)); e[i].w-=w; e[i^1].w+=w; res+=w; if (res==low)return res; } } if (!res)d[x]=-1; return res; } void dinic(){ int ans=0; while (bfs())ans+=dfs(st,inf); printf("%d ",ans); } bool spfa(){ memset(d,0x3f,sizeof d); d[st]=0; vis[q[h=t=1]=st]=true; while (h<=t){ int x=q[h++];vis[x]=false; for (int i=head[x];i;i=e[i].nxt){ int to=e[i].to; if (e[i].w&&d[to]>d[x]+e[i].cost){ d[to]=d[x]+e[i].cost; pre[to]=i; if (!vis[to]){ vis[to]=true; q[++t]=to; } } } } return d[ed]!=inf; } int update(){ int ans,mf=inf; for (int i=pre[ed];i;i=pre[e[i^1].to])mf=min(mf,e[i].w); ans=mf*d[ed]; for (int i=pre[ed];i;i=pre[e[i^1].to])e[i].w-=mf,e[i^1].w+=mf; return ans; } void MCMF(){ int ans=0; while (spfa())ans+=update(); printf("%d\n",ans); } int main(){ read(n),read(m),read(k); ed=n; for (int i=1;i<=m;i++)read(u[i]),read(v[i]),read(c[i]),read(w[i]),add(u[i],v[i],c[i],0); dinic(); for (int i=1;i<=m;i++)add(u[i],v[i],inf,w[i]); st=0; add(st,1,k,0); MCMF(); return 0; }