834: [ZJOI2010]network 网络扩容
2017-07-03 09:18
176 查看
1834: [ZJOI2010]network 网络扩容
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 3202 Solved: 1659
[Submit][Status][Discuss]
Description
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。Input
输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。Output
输出文件一行包含两个整数,分别表示问题1和问题2的答案。Sample Input
5 8 21 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
Sample Output
13 1930%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
今天早上雨大到炸裂,我们宿舍又没一个人带雨伞,然后我拿了个塑料袋挡在头顶,感觉整个人都不好了。
昨晚舍友说梦话,害我连醒三次。
题解:
第一问最大流模板。
第二问,我们在跑完最大流的边的基础上再加上几条边。
从超级原点向1连一条,流量为k,费用为0的边。
从u到·v连一条流量为INF,费用为w的边。
如果u到v可以扩容,那么它就会选费用为w的边。
#include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> #define INF 0x7fffffff using namespace std; const int N=4100; const int M=5200; struct node{ int x,y,z,cost,next,other; }sa[M*5];int len,first ; int n,m,k; int U[M],V[M],C[M],W[M]; int st,ed; void ins(int x,int y,int z,int w) { len++; sa[len].x=x; sa[len].y=y; sa[len].z=z; sa[len].cost=w; sa[len].next=first[x]; sa[len].other=len+1; first[x]=len; len++; sa[len].x=y; sa[len].y=x; sa[len].z=0; sa[len].cost=-w; sa[len].next=first[y]; sa[len].other=len-1; first[y]=len; } int head,tail,p[M*2],dep ; bool bt() { memset(dep,0,sizeof(dep));dep[st]=1; head=1;tail=2;p[head]=st; while(head!=tail) { int x=p[head]; for(int i=first[x];i!=-1;i=sa[i].next) { int y=sa[i].y; if(sa[i].z>0&&dep[y]==0) { dep[y]=dep[x]+1; p[tail]=y; tail++; } } head++; } if(dep[ed]>0) return true; return false; } int dfs(int x,int f) { if(x==ed) return f; int s=0,o; for(int i=first[x];i!=-1;i=sa[i].next) { int y=sa[i].y; if(dep[y]==dep[x]+1&&sa[i].z>0&&f>s) { o=dfs(y,min(f-s,sa[i].z)); s+=o; sa[i].z-=o; sa[sa[i].other].z+=o; } } if(s==0) dep[x]=0; return s; } int pre[M],dis[M],frpe[M],vis[M]; bool spfa() { memset(pre,-1,sizeof(pre));pre[st]=0; memset(vis,0,sizeof(vis)); for(int i=0;i<=ed;i++) dis[i]=INF; dis[st]=0; vis[st]=1; queue<int>q; q.push(st); while(!q.empty()) { int x=q.front(); q.pop();vis[x]=0; for(int i=first[x];i!=-1;i=sa[i].next) { int y=sa[i].y; if(sa[i].z && dis[y]>dis[x]+sa[i].cost) { dis[y]=dis[x]+sa[i].cost; if(!vis[y]) { vis[y]=1; q.push(y); } pre[y]=x; frpe[y]=i; } } } if(dis[ed]>=INF) return false; return true; } void MCMF() { int ans=0; while(spfa()) { int minl=INF; for(int i=ed;i!=0;i=pre[i]) { if(minl>sa[frpe[i]].z) minl=sa[frpe[i]].z; } ans+=minl*dis[ed]; for(int i=ed;i!=0;i=pre[i]) { sa[frpe[i]].z-=minl; sa[sa[frpe[i]].other].z+=minl; } } printf("%d\n",ans); } int main() { scanf("%d%d%d",&n,&m,&k); memset(first,-1,sizeof(first)); len=0; for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&U[i],&V[i],&C[i],&W[i]); ins(U[i],V[i],C[i],0); } st=1,ed=n; int ans=0; while(bt()) { ans+=dfs(st,INF); } printf("%d ",ans); st=0; ins(st,1,k,0); for(int i=1;i<=m;i++) ins(U[i],V[i],INF,W[i]); MCMF(); }
相关文章推荐
- bzoj 1834: [ZJOI2010]network 网络扩容(isap+费用流)
- BZOJ 1834 【ZJOI2010】 network 网络扩容
- 【bzoj1834】[ZJOI2010]network 网络扩容
- bzoj1834 [ZJOI2010]network 网络扩容
- bzoj1834 [ZJOI2010]network 网络扩容(费用流)
- bzoj1834: [ZJOI2010]network 网络扩容
- 【bzoj1834】[ZJOI2010]network 网络扩容
- 【BZOJ1834】[ZJOI2010]network 网络扩容 最大流+最小费用流
- 【BZOJ】1834: [ZJOI2010]network 网络扩容(最大流+费用流)
- [ZJOI2010]network 网络扩容
- BZOJ 1834: [ZJOI2010]network 网络扩容
- bzoj 1834 [ZJOI2010]network 网络扩容(MCMF)
- [网络流] bzoj1834: [ZJOI2010]network 网络扩容
- BZOJ1834 [ZJOI2010]network 网络扩容(最小费用最大流)
- 【bzoj1834】 network 网络扩容 【ZJOI2010】
- 【BZOJ 1834】 [ZJOI2010]network 网络扩容
- bzoj 1834 [ZJOI2010] network 网络扩容 题解
- 1834: [ZJOI2010]network 网络扩容
- bzoj1834[ZJOI2010]network 网络扩容【最大流+费用流】
- 【BZOJ 1834】 [ZJOI2010]network 网络扩容