您的位置:首页 > 理论基础 > 计算机网络

[BZOJ1834][ZJOI2010]network 网络扩容 最大流+费用流

2017-10-16 21:30 495 查看

1834: [ZJOI2010]network 网络扩容

Time Limit: 3 Sec Memory Limit: 64 MB Submit: 3330 Solved: 1739 [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 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

Sample Output

13 19
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10

对于第一问,我们直接跑网络流。
对于第二问,我们先建一个超级源,从这个超级源向1连一条容量为k,费用为0的边。
之后对于原图的每一条边,建一条容量无限的边,跑最小费用最大流即可。

1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<cstdlib>
5 #include<cmath>
6 #include<algorithm>
7 #define maxm 5005
8 #define maxn 1005
9 using namespace std;
10 struct data {
11     int from,to,next,w,c;
12 }e[maxm*4];
13 int head[maxn],cnt;
14 void add(int u,int v,int w,int c){e[cnt].from=u;e[cnt].next=head[u];e[cnt].to=v;e[cnt].w=w;e[cnt].c=c;head[u]=cnt++;}
15 int n,m,k;
16 int q[maxn];
17 bool vis[maxn];
18 int dis[maxn];
19 bool bfs() {
20     memset(dis,-1,sizeof(dis));
21     int h=0,t=1;
22     q[h]=1;
23     vis[1]=1;
24     dis[1]=0;
25     while(h!=t) {
26         int now=q[h];h++;vis[now]=0;if(h==1000) h=0;
27         for(int i=head[now];i>=0;i=e[i].next) {
28             int to=e[i].to;
29             if(e[i].w&&dis[to]<0) {
30                 dis[to]=dis[now]+1;
31                 if(!vis[to]){
32                     vis[to]=1;
33                     q[t++]=to;if(t==1000)t=0;
34                 }
35             }
36         }
37     }
38     return dis
!=-1;
39 }
40 int dfs(int now,int a) {
41     if(now==n||a==0) return a;
42     int flow=0,f;
43     for(int i=head[now];i>=0;i=e[i].next) {
44         int to=e[i].to;
45         if(dis[to]==dis[now]+1&&e[i].w>0) {
46             f=dfs(to,min(a,e[i].w));
47             e[i].w-=f;
48             e[i^1].w+=f;
49             flow+=f;
50             a-=f;
51             if(a==0) return flow;
52         }
53     }
54     if(!flow) dis[now]=-1;
55     return flow;
56 }
57 void work1() {
58     int ans=0;
59     while(bfs()){ans+=dfs(1,2147483647);}
60     printf("%d ",ans);
61 }
62 int cost=0;
63 bool spfa() {
64     for(int i=0;i<=n;i++) dis[i]=-1000000000;
65     int h=0,t=1;
66     q[h]=n;
67     vis
=1;
68     dis
=0;
69     while(h!=t) {
70         int now=q[h];h++;vis[now]=0;if(h==1000) h=0;
71         for(int i=head[now];i>=0;i=e[i].next) {
72             int to=e[i].to;
73             if(e[i^1].w&&dis[to]<dis[now]+e[i].c) {
74                 dis[to]=dis[now]+e[i].c;
75                 if(!vis[to]){
76                     vis[to]=1;
77                     q[t++]=to;if(t==1000)t=0;
78                 }
79             }
80         }
81     }
82     cost-=dis[0];
83     return dis[0]!=-1000000000;
84 }
85 int ans2;
86 int zkw(int now,int a) {
87     if(now==n||a==0){ans2+=cost*a;return a;}
88     int flow=0,f;vis[now]=1;
89     for(int i=head[now];i>=0;i=e[i].next) {
90         int to=e[i].to;
91         if(dis[to]==dis[now]+e[i].c&&e[i].w>0&&!vis[to]&&(f=zkw(to,min(a,e[i].w)))) {
92             e[i].w-=f;
93             e[i^1].w+=f;
94             flow+=f;
95             a-=f;
96             if(a==0) break;
97         }
98     }
99     return flow;
100 }
101 void build() {
102     int t=cnt;
103     for(int i=0;i<t;i+=2) {
104         add(e[i].from,e[i].to,1147483647,e[i].c);
105          add(e[i].to,e[i].from,0,-e[i].c);
106     }
107     add(0,1,k,0);
108     add(1,0,0,0);
109     for(int i=0;i<t;i++) e[i].c=0;
110 }
111 void work2() {
112     ans2=0;cost=0;
113     build();
114     memset(vis,0,sizeof(vis));
115     while(spfa()) {
116         do {
117             memset(vis,0,sizeof(vis));
118         }while(zkw(0,2147483647));
119         memset(vis,0,sizeof(vis));cost=0;
120     }
121     printf("%d",ans2);
122 }
123 int main() {
124     memset(head,-1,sizeof(head));
125     scanf("%d%d%d",&n,&m,&k);
126     for(int i=1;i<=m;i++) {
127         int u,v,w,c;
128         scanf("%d%d%d%d",&u,&v,&w,&c);
129         add(u,v,w,c);add(v,u,0,-c);
130     }
131     work1();
132     work2();
133 }


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: