bzoj1834 [ZJOI2010]network 网络扩容(费用流)
2018-02-10 16:37
513 查看
bzoj1834 [ZJOI2010]network 网络扩容
原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1834题意:
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。
求:
1、在不扩容的情况下,1到N的最大流;
2、将1到N的最大流增加K所需的最小扩容费用。
数据范围
N<=1000,M<=5000,K<=10
题解:
1.最大流
2.残量网络上跑费用流
注意,2要新建源汇以向1节点补充K的流量,且保证n到T的流量最大流为K。
数据范围是错的,n<=6000,m<=20000左右。而且测出来不是RE是WA,为此查错了一中午。
代码:
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=6115; const int M=50115; const int inf=0x3f3f3f3f; queue<int> Q; int n,m,K,S,preS,T,preT; int head[N],nxt[4*N],w[4*M],to[4*N],c[4*M],num=1,U[M],V[M],C[M],W[M],ans=0,dis[N],pre[N][2],dep ; bool inq ,vis ; void build(int u,int v,int cc,int ww) { num++; to[num]=v; nxt[num]=head[u]; w[num]=ww; c[num]=cc; head[u]=num; num++; to[num]=u; nxt[num]=head[v]; w[num]=0; c[num]=-cc; head[v]=num; } bool bfs() { memset(vis,0,sizeof(vis)); dis[S]=1; vis[S]=1; Q.push(S); while(!Q.empty()) { int u=Q.front(); Q.pop(); for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(vis[v]||w[i]<=0) continue; vis[v]=1; dep[v]=dep[u]+1; Q.push(v); } } return vis[T]; } int dfs(int u,int d) { if(u==T||d==0) return d; int ret=0; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; if(dep[v]!=dep[u]+1||w[i]<=0) continue; int flow=dfs(v,min(d,w[i])); d-=flow; ret+=flow; w[i]-=flow; w[i^1]+=flow; if(!d) break; } if(ret==0) dep[u]=-1; return ret; } bool spfa() { memset(dis,0x3f,sizeof(dis)); memset(inq,0,sizeof(inq)); dis[S]=0; inq[S]=1; Q.push(S); while(!Q.empty()) { int u=Q.front(); Q.pop(); inq[u]=0; for(int i=head[u];i;i=nxt[i]) { if(w[i]<=0) continue; int v=to[i]; if(dis[v]>dis[u]+c[i]) { dis[v]=dis[u]+c[i]; pre[v][0]=u,pre[v][1]=i; if(!inq[v]) inq[v]=1,Q.push(v); } } } return dis[T]<inf; } int get() { int flow=inf; int tmp=T; int ret=0; while(tmp!=S) { flow=min(flow,w[pre[tmp][1]]); tmp=pre[tmp][0]; } tmp=T; while(tmp!=S) { ret+=flow*c[pre[tmp][1]]; w[pre[tmp][1]]-=flow; w[pre[tmp][1]^1]+=flow; tmp=pre[tmp][0]; } return ret; } int main() { scanf("%d%d%d",&n,&m,&K); S=1,T=n,preS=n+1,preT=n+2; for(int i=1;i<=m;i++) scanf("%d%d%d%d",&U[i],&V[i],&W[i],&C[i]),build(U[i],V[i],0,W[i]); while(bfs()) ans+=dfs(S,inf); printf("%d ",ans); swap(T,preT); swap(S,preS); build(preT,T,0,K); build(S,preS,0,K); ans=0; for(int i=1;i<=m;i++) build(U[i],V[i],C[i],K); while(spfa()) ans+=get(); printf("%d\n",ans); return 0; }
相关文章推荐
- BZOJ 1834 [ZJOI2010]network 网络扩容(费用流)
- bzoj 1834 [ZJOI2010] network 网络扩容(费用流)
- [BZOJ1834][ZJOI2010]network 网络扩容 最大流+费用流
- 【最大流】【费用流】bzoj1834 [ZJOI2010]network 网络扩容
- bzoj 1834: [ZJOI2010]network 网络扩容 网络流+费用流
- BZOJ1834 [ZJOI2010]network 网络扩容 【最大流,费用流】
- BZOJ_1834_[ZJOI2010]network 网络扩容_费用流
- BZOJ 1834: [ZJOI2010]network 网络扩容(网络流+费用流)
- 【bzoj1834】[ZJOI2010]network 网络扩容 费用流
- bzoj1834 [ZJOI2010]network 网络扩容 最大流+费用流
- BZOJ1834 [ZJOI2010]network 网络扩容
- 【bzoj1834】[ZJOI2010]network 网络扩容
- [BZOJ1834][ZJOI2010]网络扩容(费用流)
- BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)
- 【BZOJ1834】[ZJOI2010]network 网络扩容 最大流+最小费用流
- bzoj1834 [ZJOI2010]network 网络扩容
- [BZOJ1834]ZJOI2010网络扩容|最大流|费用流
- bzoj 1834: [ZJOI2010]network 网络扩容 -- 最大流+费用流
- 【bzoj1834】[ZJOI2010]network 网络扩容
- bzoj 1834 [ZJOI2010]network 网络扩容(MCMF)