BZOJ1834: [ZJOI2010]network 网络扩容
2016-12-23 07:59
387 查看
1834: [ZJOI2010]network 网络扩容
Time Limit: 3 Sec Memory Limit: 64 MBSubmit: 2824 Solved: 1428
[Submit][Status][Discuss]
题解:
第一问直接用最大流求解就可以了。
在求完第一问之后不用重新构图,直接用第一问的残余网络(也就是有一些边在跑完最大流之后还会有一些剩余流量)+每条边我们再建一个容量为inf,费用为W的边(要注意跑第一问的所有边费用都是0),再新建立一个源点S,从S向1连一条容量为K的边,跑最小费用最大流。
可以这样想:我们这样构图之后每个点之间会有两条正向边和两条反向边。这两对正反向边中,有一对是第一问跑完最大流后,容量的剩余,费用为0,可以在扩容之后免费使用,然而想用到多余的流量,就要跑刚才新建的边,每通过一个流量就相当于需要扩容一次,也需要付出Wi的代价,为了使花费最少且能使k个容量全部到达n,跑最小费用最大流
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; const int N=3005; const int M=100005; const int inf=1e9; int n,m,K,cnt=1,ans; int from[M],to[M],nxt[M],lj ,w[M],v[M],p[M]; void add(int f,int t,int ww,int vv) { cnt++,from[cnt]=f,to[cnt]=t,nxt[cnt]=lj[f],lj[f]=cnt,w[cnt]=ww,v[cnt]=vv; cnt++,from[cnt]=t,to[cnt]=f,nxt[cnt]=lj[t],lj[t]=cnt,w[cnt]=0,v[cnt]=-vv; } queue<int>Q; int d ,bef ,S; bool vis ; bool bfs() { memset(d,0,sizeof d); d[1]=1; Q.push(1); while(!Q.empty()) { int x=Q.front(); Q.pop(); for(int i=lj[x];i;i=nxt[i]) if(w[i]&&!d[to[i]]) { d[to[i]]=d[x]+1; Q.push(to[i]); } } if(d ) return true; return false; } int dfs(int x,int v) { if(x==n||v==0) return v; int ret=0; for(int i=lj[x];i;i=nxt[i]) if(d[to[i]]==d[x]+1) { int f=dfs(to[i],min(v,w[i])); w[i]-=f; w[i^1]+=f; v-=f; ret+=f; if(v==0) break; } if(ret==0) d[x]=-1; return ret; } void Dinic() { while(bfs()) ans+=dfs(1,inf); } bool Spfa() { for(int i=0;i<=n;i++) d[i]=inf; d[S]=0; Q.push(S); while(!Q.empty()) { int x=Q.front(); Q.pop(); vis[x]=false; for(int i=lj[x];i;i=nxt[i]) if(d[to[i]]>d[x]+v[i]&&w[i]) { d[to[i]]=d[x]+v[i]; bef[to[i]]=i; if(!vis[to[i]]) { vis[to[i]]=true; Q.push(to[i]); } } } if(d !=inf) return true; else return false; } void Build() { S=0; add(S,1,K,0); for(int i=1;i<=m;i++) add(from[i<<1],to[i<<1],inf,p[i]); } void Exflow() { ans=0; while(Spfa()) { int x=n,cost=0,flow=inf,sid; while(x!=S) { sid=bef[x]; cost+=v[sid]; flow=min(flow,w[sid]); x=from[sid]; } ans+=cost*flow; x=n; while(x!=S) { sid=bef[x]; w[sid]-=flow; w[sid^1]+=flow; x=from[sid]; } } } int main() { scanf("%d%d%d",&n,&m,&K); int x,y,z; for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&x,&y,&z,&p[i]); add(x,y,z,0); } Dinic(); printf("%d ",ans); Build(); Exflow(); printf("%d\n",ans); }
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
HINT
Source
Day1[Submit][Status][Discuss]
相关文章推荐
- BZOJ1834 [ZJOI2010] network 网络扩容
- BZOJ 1834 [ZJOI2010]network 网络扩容
- bzoj1834 [ZJOI2010]network 网络扩容
- 【最大流/费用流】BZOJ1834-[ZJOI2010]network 网络扩容
- bzoj 1834 [ZJOI2010]network 网络扩容(MCMF)
- 【最大流】【费用流】bzoj1834 [ZJOI2010]network 网络扩容
- 【bzoj1834】[ZJOI2010]network 网络扩容 费用流
- bzoj 1834 [ZJOI2010] network 网络扩容 题解
- 【bzoj1834】[ZJOI2010]network 网络扩容(wikioi1362)
- 【BZOJ】1834: [ZJOI2010]network 网络扩容(最大流+费用流)
- BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)
- [BZOJ 1834] [ZJOI2010]network 网络扩容
- 【BZOJ 1834】 [ZJOI2010]network 网络扩容
- bzoj 1834: [ZJOI2010]network 网络扩容(isap+费用流)
- 【bzoj1834】[ZJOI2010]network 网络扩容
- [BZOJ1834][ZJOI2010]network 网络扩容(最大流+费用流)
- 【BZOJ 1834】 [ZJOI2010]network 网络扩容
- bzoj1834 [ZJOI2010]network 网络扩容
- bzoj1834[ZJOI2010]network 网络扩容【最大流+费用流】
- bzoj 1834: [ZJOI2010]network 网络扩容