[ZJOI2010]网络扩容
2017-03-23 11:19
260 查看
题目描述
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。输入输出格式
输入格式:输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
输出格式:
输出文件一行包含两个整数,分别表示问题1和问题2的答案。
输入输出样例
输入样例#1:5 8 2 1 2 5 8 2 5 9 9 5 1 6 2 5 1 1 8 1 2 8 7 2 5 4 9 1 2 1 1 1 4 2 1
输出样例#1:
13 19
说明
30%的数据中,N<=100100%的数据中,N<=1000,M<=5000,K<=10
数据规模并不准。
思路:最大流+构图+费用流
还是看了题解,构图的精髓没有掌握啊。
最大流:s->(q->z +w 0 -0 0)->t
费用流:ys-> (ys-> +k 0 -0 0)->s->残余免费网络||(q->z +k f -0 -f)->t
代码实现:
#include<cstdio> #include<cstring> const int inf=2139062143; const int maxn=6000; const int maxm=500000; int n,m,k,s,t,ys,tw,tc; int eq[maxn],ez[maxn],ew[maxn],ef[maxn]; int a,b,c,d; inline int min_(int x,int y){return x<y?x:y;} int h[maxn],hs=1; struct edge{int s,n,w,f;}e[maxm]; void add(int q,int z,int w,int f){ e[++hs]=(edge){z,h[q],w,f},h[q]=hs; e[++hs]=(edge){q,h[z],0,-f},h[z]=hs; } int de[maxn],q[maxm],head,tail; bool bfs(){ memset(de,0,sizeof(de)); head=tail=0; q[head++]=s,de[s]=1; while(head>tail){ a=q[tail++]; for(int i=h[a];i;i=e[i].n) if(!de[e[i].s]&&e[i].w){ de[e[i].s]=de[a]+1; if(e[i].s==t) return true; q[head++]=e[i].s; } } return false; } int ap(int k,int w){ if(k==t) return w; int uw=w; for(int i=h[k];uw&&i;i=e[i].n) if(de[e[i].s]==de[k]+1&&e[i].w){ int nw=ap(e[i].s,min_(uw,e[i].w)); if(nw) e[i].w-=nw,e[i^1].w+=nw,uw-=nw; else de[e[i].s]=0; } return w-uw; } void Dinic(){while(bfs()) tw+=ap(s,inf);} int w[maxn],pp[maxn],pw[maxn]; void spfa(){ memset(w,0x7f,sizeof(w)); head=tail=0; q[head++]=ys,w[ys]=0; while(head>tail){ a=q[tail++]; for(int i=h[a];i;i=e[i].n) if(e[i].w&&1ll+w[a]+e[i].f-1<w[e[i].s]){ pp[e[i].s]=a,pw[e[i].s]=i; q[head++]=e[i].s; w[e[i].s]=w[a]+e[i].f; } } } int mcmf(int k,int v){ if(k==ys) return v; int ret=mcmf(pp[k],min_(e[pw[k]].w,v)); e[pw[k]].w-=ret; e[pw[k]^1].w+=ret; return ret; } bool Cost(){ spfa(); if(w[t]==inf) return false; tc+=w[t]*mcmf(t,inf); } int main(){ freopen("networkzj2010.in","r",stdin); freopen("networkzj2010.out","w",stdout); scanf("%d%d%d",&n,&m,&k); s=1,t=n; for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&eq[i],&ez[i],&ew[i],&ef[i]); add(eq[i],ez[i],ew[i],0); } Dinic(); ys=0,add(ys,s,k,0); for(int i=1;i<=m;i++) add(eq[i],ez[i],k,ef[i]); while(Cost()); printf("%d %d\n",tw,tc); return 0; }
题目来源:洛谷
相关文章推荐
- 洛谷P2604 [ZJOI2010]网络扩容
- [BZOJ1834][ZJOI2010]网络扩容(最大流+费用流)
- bzoj 1834 [ZJOI2010] network 网络扩容 题解
- bzoj1834 [ZJOI2010]network 网络扩容
- 【BZOJ 1834】 [ZJOI2010]network 网络扩容
- [BZOJ1834][ZJOI2010][最大流][最小费用最大流]网络扩容
- bzoj1834: [ZJOI2010]network 网络扩容(最小费用最大流)
- ZJOI2010——network 网络扩容(费用流)
- BZOJ 1834: [ZJOI2010]network 网络扩容(网络流+费用流)
- BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)
- 【BZOJ】1834 [ZJOI2010]network 网络扩容
- [BZOJ1834]ZJOI2010网络扩容|最大流|费用流
- [bzoj1834][ZJOI2010]network 网络扩容
- 【ZJOI2010】network-网络扩容
- [ZJOI2010] 网络扩容
- bzoj 1834: [ZJOI2010]network 网络扩容(isap+费用流)
- BZOJ1834 [ZJOI2010] network 网络扩容
- 1834: [ZJOI2010]network 网络扩容 (最小费用最大流模板)
- BZOJ1834: [ZJOI2010]network 网络扩容
- Bzoj:[ZJOI2010]network 网络扩容:网络流,最大流+费用流