P2604 [ZJOI2010]网络扩容
Posted wangyiding2003
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2604 [ZJOI2010]网络扩容相关的知识,希望对你有一定的参考价值。
题目描述
给定一张有向图,每条边都有一个容量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<=100
100%的数据中,N<=1000,M<=5000,K<=10
思路
有点暴力。先跑一遍dinic,求出第一问的解,再重新建图,讲扩容记为容量inf,费用的边,最后新建t点,容量为maxflow+k,跑最大流最小费用,即可得到ans。
代码
#include<bits/stdc++.h> #define N 10700 #define M 107000 #define inf 1<<29 using namespace std; struct node int x,y,z,p,next; e[M*2]; int tot=1,head[N],maxflow=0,ans=0; int x[M],y[M],z[M],cost[M]; int n,m,s,t,K; void add(int x,int y,int z,int p) e[++tot].y=y;e[tot].z=z;e[tot].p=p;e[tot].next=head[x];head[x]=tot; e[++tot].y=x;e[tot].z=0;e[tot].p=-p;e[tot].next=head[y];head[y]=tot; int incf[N],v[N],pre[N],d[N]; queue<int> q; bool bfs() memset(d,0,sizeof(d)); while(q.size()) q.pop(); q.push(s);d[s]=1; while(q.size()) int x=q.front();q.pop(); for(int i=head[x];i;i=e[i].next) int y=e[i].y,z=e[i].z; if(z&&!d[y]) q.push(y);d[y]=d[x]+1; if(y==t) return 1; return 0; int dinic(int x,int flow) if(x==t) return flow; int rest=flow,k; for(int i=head[x];i;i=e[i].next) int y=e[i].y,z=e[i].z; if(z&&d[y]==d[x]+1) k=dinic(y,min(rest,z)); if(!k) d[y]=0; e[i].z-=k; e[i^1].z+=k; rest-=k; return flow-rest; bool spfa() queue<int> q; memset(d,0x3f,sizeof(d));// 0xcf memset(v,0,sizeof(v)); q.push(s);d[s]=0;v[s]=1; incf[s]=inf; while(q.size()) int x=q.front();v[x]=0;q.pop(); for(int i=head[x];i;i=e[i].next) int y=e[i].y,z=e[i].z; if(!z) continue; if(d[y]>d[x]+e[i].p)//d[y]<d[x]+e[i].p d[y]=d[x]+e[i].p; incf[y]=min(incf[x],z); pre[y]=i; if(!v[y]) v[y]=1,q.push(y); if(d[t]==0x3f3f3f3f) return false;//0xcfcfcfcf return true; void update() int x=t; while(x!=s) int i=pre[x]; e[i].z-=incf[t]; e[i^1].z+=incf[t]; x=e[i^1].y; maxflow+=incf[t]; ans+=d[t]*incf[t]; void rebuild() s=1;t=n+1; memset(head,0,sizeof(head));tot=1; for(int i=1;i<=m;i++) add(x[i],y[i],z[i],0); add(x[i],y[i],inf,cost[i]); add(n,n+1,maxflow+K,0); int main() int flow=0; cin>>n>>m>>K; for(int i=1;i<=m;i++) scanf("%d%d%d%d",&x[i],&y[i],&z[i],&cost[i]); add(x[i],y[i],z[i],0); s=1;t=n; while(bfs()) while(flow=dinic(s,inf)) maxflow+=flow; cout<<maxflow<<" "; rebuild(); while(spfa()) update(); cout<<ans<<endl; return 0;
以上是关于P2604 [ZJOI2010]网络扩容的主要内容,如果未能解决你的问题,请参考以下文章