【BZOJ 1834】 [ZJOI2010]network 网络扩容
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 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 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 19
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
第一问最大流
第二问
建立超级源和超级汇,超级源向1连边,容量为K,n向超级汇连边,容量同上。原来的每条边再建立一条,容量为inf,费用为W,在原图上增广,跑最小费用最大流
但是!!!新边一定要在求完第一问之后再建。。。
代码量略大。。。不过我都上套板子。。。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<iostream> 5 using namespace std; 6 const int N=55555,inf=1000000; 7 struct ee{int to,next,f,w;}e[N*2]; 8 int S,T,cnt=1,n,k,ans1,ans2,timer,m,u[N],v[N],w[N],c[N],mid; 9 int head[N],dis[N],pre[N],q[N]; 10 bool inq[N],flag=1; 11 void ins(int u,int v,int f,int w){ 12 e[++cnt].to=v,e[cnt].next=head[u],e[cnt].f=f,e[cnt].w=w,head[u]=cnt; 13 e[++cnt].to=u,e[cnt].next=head[v],e[cnt].f=0,e[cnt].w=-w,head[v]=cnt; 14 } 15 bool spfa(){ 16 for (int i=1;i<=T;i++) dis[i]=inf; 17 int h=0,t=1; 18 q[t]=S;dis[S]=0;inq[S]=1; 19 while (h!=t){ 20 int now=q[++h];if(h==2501) h=0; 21 for (int i=head[now];i;i=e[i].next){ 22 int v=e[i].to; 23 if (dis[v]>dis[now]+e[i].w&&e[i].f){ 24 dis[v]=dis[now]+e[i].w; 25 pre[v]=i; 26 if (!inq[v]){ 27 q[++t]=v;if (t==2501) t=0; 28 inq[v]=1; 29 } 30 } 31 } 32 inq[now]=0; 33 } 34 if (dis[T]==inf) return 0; 35 return 1; 36 } 37 38 void updata(){ 39 int tmp=T,flow=inf; 40 while (tmp!=S){ 41 int l=pre[tmp],v=e[l].to; 42 flow=min(flow,e[l].f); 43 tmp=e[l^1].to; 44 } 45 tmp=T; 46 while (tmp!=S){ 47 int l=pre[tmp],v=e[l].to; 48 e[l].f-=flow;e[l^1].f+=flow; 49 tmp=e[l^1].to; 50 } 51 mid+=flow; 52 if(mid>=k) flag=0; 53 ans2+=dis[T]*flow; 54 } 55 56 bool bfs(){ 57 for (int i=1;i<=T;i++) dis[i]=inf; 58 int h=0,t=1,now; 59 q[1]=1;dis[1]=0; 60 while(h!=t){ 61 now=q[++h]; 62 for (int i=head[now];i;i=e[i].next){ 63 int v=e[i].to; 64 if (e[i].f&&dis[now]+1<dis[v]){ 65 dis[v]=dis[now]+1; 66 if (v==n)return 1; 67 q[++t]=v; 68 } 69 } 70 } 71 if (dis[n]==inf) return 0; return 1; 72 } 73 74 int dinic(int now,int f){ 75 if (now==n) return f; 76 int rest=f; 77 for (int i=head[now];i;i=e[i].next){ 78 int v=e[i].to; 79 if (e[i].f&&dis[v]==dis[now]+1&&rest){ 80 int t=dinic(v,min(rest,e[i].f)); 81 if (!t) dis[v]=0; 82 e[i].f-=t; 83 e[i^1].f+=t; 84 rest-=t; 85 //if(t) printf("%d %d %d\n",now,v,e[i].f); 86 } 87 } 88 return f-rest; 89 } 90 91 int main(){ 92 scanf("%d%d%d",&n,&m,&k); 93 S=0,T=n+1; 94 for (int i=1;i<=m;i++){ 95 scanf("%d%d%d%d",&u[i],&v[i],&c[i],&w[i]); 96 ins(u[i],v[i],c[i],0); 97 } 98 ins(S,1,k,0);ins(n,T,k,0); 99 while(bfs()) 100 ans1+=dinic(1,inf); 101 for (int i=1;i<=m;i++)ins(u[i],v[i],inf,w[i]); 102 while(flag&&spfa()) 103 updata(); 104 printf("%d %d",ans1,ans2); 105 }