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

[ZJOI2010]网络扩容 (最大流 + 费用流)

2017-10-15 13:53 381 查看
题目描述
给定一张有向图,每条边都有一个容量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

 

集最大流和费用流与一身。。。。

扩容的时候 只需要从0建一条向1流量为k的边 费用为0

其他边之间的流量为INF 费用不变

 





1 /*
2     有重边对 max_flow()中找前驱有影响
3     所以在node中记录前驱就好了
4 */
5 #include<queue>
6 #include<cstdio>
7 #include<cstring>
8 #include<iostream>
9 #define MAXN 200010
10
11 using namespace std;
12
13 const int INF=0x7fffffff;
14
15 int n,m,k,MAX_FLOW,MIN_FEE,src;
16
17 int x,y,val,cost[MAXN],a[MAXN];
18
19 struct node {
20     int from;
21     int to;
22     int next;
23     int val;
24     int cost;
25     int save;
26 };
27 node e[MAXN];
28
29 bool vis[MAXN];
30
31 int head[MAXN],tot=1;
32
33 int fee[MAXN],pre[MAXN];
34
35 queue<int> q;
36
37 inline void read(int&x) {
38     int f=1;x=0;char c=getchar();
39     while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
40     while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-48;c=getchar();}
41     x=x*f;
42 }
43
44 inline void add(int x,int y,int val,int cost) {
45     e[++tot].to=y;
46     e[tot].from=x;
47     e[tot].val=val;
48     e[tot].cost=cost;
49     e[tot].next=head[x];
50     head[x]=tot;
51 }
52
53 inline void add1(int x,int y,int val,int save) {
54     e[++tot].to=y;
55     e[tot].from=x;
56     e[tot].val=val;
57     e[tot].save=save;
58     e[tot].next=head[x];
59     head[x]=tot;
60 }
61
62 inline void add_edge(int x,int y,int val,int cost) {
63     add(x,y,val,cost);
64     add(y,x,0,-cost);
65 }
66
67 inline void add_edge1(int x,int y,int val,int cost) {
68     add1(x,y,val,cost);
69     add1(y,x,0,-cost);
70 }
71
72 inline bool spfa_flow() {
73     for(int i=0;i<=n;i++) vis[i]=false,pre[i]=-1;
74     while(!q.empty()) q.pop();
75     q.push(src);
76     fee[src]=0;
77     pre[src]=0;
78     vis[src]=true;
79     while(!q.empty()) {
80         int u=q.front();
81         q.pop();
82         for(int i=head[u];i;i=e[i].next) {
83             int to=e[i].to;
84             if(!vis[to]&&e[i].val) {
85                 pre[to]=i;
86                 vis[to]=true;
87                 if(to==n) return true;
88                 q.push(to);
89             }
90         }
91     }
92     return false;
93 }
94
95 inline int max_flow() {
96     int flow=INF;
97     for(int i=pre
;i;i=pre[e[i^1].to])
98       flow=min(flow,e[i].val);
99     for(int i=pre
;i;i=pre[e[i^1].to])
100       e[i].val-=flow,e[i^1].val+=flow;
101     return flow;
102 }
103
104 inline void change() {
105     int pot=tot;
106     for(int i=4;i<=pot;i++)
107       if(i%2==0) add_edge(e[i].from,e[i].to,INF,e[i].save);
108     e[2].val=k;
109     e[3].val=0;
110     return;
111 }
112
113 inline bool spfa_fee() {
114     for(int i=0;i<=n;i++) vis[i]=false,pre[i]=-1,fee[i]=INF;
115     while(!q.empty()) q.pop();
116     q.push(0);
117     fee[0]=0;
118     vis[0]=true;
119     pre[0]=0;
120     a[0]=999999;
121     while(!q.empty()) {
122         int u=q.front();
123         q.pop();
124         vis[u]=false;
125         for(int i=head[u];i!=-1;i=e[i].next) {
126             int to=e[i].to;
127             if(fee[to]>fee[u]+e[i].cost&&e[i].val>0) {
128                 a[to]=min(a[u],e[i].val);
129                 fee[to]=fee[u]+e[i].cost;
130                 pre[to]=i;
131                 if(!vis[to]) {
132                     vis[to]=true;
133                     q.push(to);
134                 }
135             }
136         }
137     }
138     return fee
!=INF;
139 }
140
141 inline int MIN_fee() {
142     int Flow=INF;
143     for(int i=pre
;i;i=pre[e[i].from])
144       Flow=min(Flow,e[i].val);
145     for(int i=pre
;i;i=pre[e[i].from])
146       e[i].val-=Flow,e[i^1].to+=Flow;
147     return Flow;
148 }
149
150 int main() {
151     read(n);read(m);read(k);
152     memset(head,-1,sizeof head);
153     add_edge1(src,1,1<<30,0);
154     for(int i=1;i<=m;i++) {
155         read(x);read(y);read(val);read(cost[i]);
156         add_edge1(x,y,val,cost[i]);
157     }
158     while(spfa_flow())
159         MAX_FLOW+=max_flow();
160     change();
161     while(spfa_fee()) {
162         int FLOW=MIN_fee();
163         MIN_FEE+=FLOW*fee
;
164     }
165     printf("%d %d\n",MAX_FLOW,MIN_FEE);
166     return 0;
167 }


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