CodeForces 362E Petya and Pipes

Petya and Pipes

Time Limit: 1000ms
Memory Limit: 262144KB
This problem will be judged on  CodeForces. Original ID: 362E
64-bit integer IO format: %I64d      Java class name: (Any)
 
A little boy Petya dreams of growing up and becoming the Head Berland Plumber. He is thinking of the problems he will have to solve in the future. Unfortunately, Petya is too inexperienced, so you are about to solve one of such problems for Petya, the one he's the most interested in.

 

The Berland capital has n water tanks numbered from 1 to n. These tanks are connected by unidirectional pipes in some manner. Any pair of water tanks is connected by at most one pipe in each direction. Each pipe has a strictly positive integer width. Width determines the number of liters of water per a unit of time this pipe can transport. The water goes to the city from the main water tank (its number is 1). The water must go through some pipe path and get to the sewer tank with cleaning system (its number is n).

Petya wants to increase the width of some subset of pipes by at most k units in total so that the width of each pipe remains integer. Help him determine the maximum amount of water that can be transmitted per a unit of time from the main tank to the sewer tank after such operation is completed.

 

Input

The first line contains two space-separated integers n and k (2 ≤ n ≤ 50, 0 ≤ k ≤ 1000). Then follow n lines, each line contains n integers separated by single spaces. The i + 1-th row and j-th column contain number cij — the width of the pipe that goes from tank i to tank j (0 ≤ cij ≤ 106, cii = 0). If cij = 0, then there is no pipe from tank i to tank j.

 

Output

Print a single integer — the maximum amount of water that can be transmitted from the main tank to the sewer tank per a unit of time.

 

Sample Input

Input
5 7
0 1 0 2 0
0 0 4 10 0
0 0 0 0 5
0 0 0 0 10
0 0 0 0 0
Output
10
Input
5 10
0 1 0 0 0
0 0 2 0 0
0 0 0 3 0
0 0 0 0 4
100 0 0 0 0
Output
5

Hint

In the first test Petya can increase width of the pipe that goes from the 1st to the 2nd water tank by 7 units.

In the second test Petya can increase width of the pipe that goes from the 1st to the 2nd water tank by 4 units, from the 2nd to the 3rd water tank by 3 units, from the 3rd to the 4th water tank by 2 units and from the 4th to 5th water tank by 1 unit.

 

Source

 
解题:拆边费用流。把原来的边拆成两条,一条流量为原来的,费用为0,另一条费用为1流量为k.
 
然后进行最小费用路径增广,我们每次增广,d[T】存的是从源到汇,单位流量最便宜的一条路径。。。。一旦费用超过k即停止算法。
 
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <climits>
 7 #include <vector>
 8 #include <queue>
 9 #include <cstdlib>
10 #include <string>
11 #include <set>
12 #include <stack>
13 #define LL long long
14 #define pii pair<int,int>
15 #define INF 0x3f3f3f3f
16 using namespace std;
17 const int maxn = 110;
18 struct arc {
19     int to,flow,cost,next;
20     arc(int x = 0,int y = 0,int z = 0,int nxt = -1) {
21         to = x;
22         flow = y;
23         cost = z;
24         next = nxt;
25     }
26 };
27 arc e[10000];
28 int head[maxn],d[maxn],p[maxn],S,T,n,k,tot;
29 bool in[maxn];
30 void add(int u,int v,int flow,int cost) {
31     e[tot] = arc(v,flow,cost,head[u]);
32     head[u] = tot++;
33     e[tot] = arc(u,0,-cost,head[v]);
34     head[v] = tot++;
35 }
36 bool spfa() {
37     queue<int>q;
38     for(int i = 0; i <= n; ++i) {
39         d[i] = INF;
40         p[i] = -1;
41         in[i] = false;
42     }
43     d[S] = 0;
44     q.push(S);
45     while(!q.empty()) {
46         int u = q.front();
47         q.pop();
48         for(int i = head[u]; ~i; i = e[i].next) {
49             if(e[i].flow && d[e[i].to] > d[u] + e[i].cost) {
50                 d[e[i].to] = d[u] + e[i].cost;
51                 p[e[i].to] = i;
52                 q.push(e[i].to);
53             }
54         }
55     }
56     return p[T] > -1;
57 }
58 int solve() {
59     int cost = 0,flow = 0;
60     while(spfa()) {
61         int theMin = INF;
62         for(int i = p[T]; ~i; i = p[e[i^1].to])
63             theMin = min(theMin,e[i].flow);
64         if(cost + d[T]*theMin > k) return flow + (k - cost)/d[T];
65         flow += theMin;
66         cost += d[T]*theMin;
67         for(int i = p[T]; ~i; i = p[e[i^1].to]) {
68             e[i].flow -= theMin;
69             e[i^1].flow += theMin;
70         }
71     }
72     return flow;
73 }
74 int main() {
75     while(~scanf("%d %d",&n,&k)) {
76         memset(head,-1,sizeof(head));
77         S = 0;
78         T = n-1;
79         int tmp;
80         for(int i = tot = 0; i < n; ++i)
81             for(int j = 0; j < n; ++j) {
82                 scanf("%d",&tmp);
83                 if(tmp) {
84                     add(i,j,tmp,0);
85                     add(i,j,k,1);
86                 }
87             }
88         printf("%d\n",solve());
89     }
90     return 0;
91 }
View Code

 

上面代码可以AC,但是忘记标记入队点了。。。。。。^_^..

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <climits>
 7 #include <vector>
 8 #include <queue>
 9 #include <cstdlib>
10 #include <string>
11 #include <set>
12 #include <stack>
13 #define LL long long
14 #define pii pair<int,int>
15 #define INF 0x3f3f3f3f
16 using namespace std;
17 const int maxn = 110;
18 struct arc {
19     int to,flow,cost,next;
20     arc(int x = 0,int y = 0,int z = 0,int nxt = -1) {
21         to = x;
22         flow = y;
23         cost = z;
24         next = nxt;
25     }
26 };
27 arc e[10000];
28 int head[maxn],d[maxn],p[maxn],S,T,n,k,tot;
29 bool in[maxn];
30 void add(int u,int v,int flow,int cost) {
31     e[tot] = arc(v,flow,cost,head[u]);
32     head[u] = tot++;
33     e[tot] = arc(u,0,-cost,head[v]);
34     head[v] = tot++;
35 }
36 bool spfa() {
37     queue<int>q;
38     for(int i = 0; i <= n; ++i) {
39         d[i] = INF;
40         p[i] = -1;
41         in[i] = false;
42     }
43     d[S] = 0;
44     q.push(S);
45     while(!q.empty()) {
46         int u = q.front();
47         q.pop();
48         in[u] = false;
49         for(int i = head[u]; ~i; i = e[i].next) {
50             if(e[i].flow && d[e[i].to] > d[u] + e[i].cost) {
51                 d[e[i].to] = d[u] + e[i].cost;
52                 p[e[i].to] = i;
53                 if(!in[e[i].to]){
54                     in[e[i].to] = true;
55                     q.push(e[i].to);
56                 }
57             }
58         }
59     }
60     return p[T] > -1;
61 }
62 int solve() {
63     int cost = 0,flow = 0;
64     while(spfa()) {
65         int theMin = INF;
66         for(int i = p[T]; ~i; i = p[e[i^1].to])
67             theMin = min(theMin,e[i].flow);
68         if(cost + d[T]*theMin > k) return flow + (k - cost)/d[T];
69         flow += theMin;
70         cost += d[T]*theMin;
71         for(int i = p[T]; ~i; i = p[e[i^1].to]) {
72             e[i].flow -= theMin;
73             e[i^1].flow += theMin;
74         }
75     }
76     return flow;
77 }
78 int main() {
79     while(~scanf("%d %d",&n,&k)) {
80         memset(head,-1,sizeof(head));
81         S = 0;
82         T = n-1;
83         int tmp;
84         for(int i = tot = 0; i < n; ++i)
85             for(int j = 0; j < n; ++j) {
86                 scanf("%d",&tmp);
87                 if(tmp) {
88                     add(i,j,tmp,0);
89                     add(i,j,k,1);
90                 }
91             }
92         printf("%d\n",solve());
93     }
94     return 0;
95 }
View Code

 

转载于:https://www.cnblogs.com/crackpotisback/p/4041824.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值