【BZOJ1834】 [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

Sample Output

13 19

30%的数据中,N<=100

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

Solution

第一问可以直接用最大流跑。

第二问新建源然后向旧源连一条容量为K, 费用0的边。其他就是原来的连容量c,费用0,新加的连容量inf,费用W。最后跑费用流即可。

Code

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <cmath>
  5 #include <queue>
  6
  7 #ifdef WIN32
  8     #define LL "%I64d"
  9 #else
 10     #define LL "%lld"
 11 #endif
 12
 13 #ifdef CT
 14     #define debug(...) printf(__VA_ARGS__)
 15     #define setfile()
 16 #else
 17     #define debug(...)
 18     #define filename ""
 19     #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout)
 20 #endif
 21
 22 #define R register
 23 #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
 24 #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
 25 #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
 26 #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
 27 #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
 28 #define cabs(_x) ((_x) < 0 ? (- (_x)) : (_x))
 29 char B[1 << 15], *S = B, *T = B;
 30 inline int F()
 31 {
 32     R char ch; R int cnt = 0; R bool minus = 0;
 33     while (ch = getc(), (ch < ‘0‘ || ch > ‘9‘) && ch != ‘-‘) ;
 34     ch == ‘-‘ ? minus = 1 : cnt = ch - ‘0‘;
 35     while (ch = getc(), ch >= ‘0‘ && ch <= ‘9‘) cnt = cnt * 10 + ch - ‘0‘;
 36     return minus ? -cnt : cnt;
 37 }
 38 #define maxn 1010
 39 #define maxm 100010
 40 struct edge
 41 {
 42     int a, b, w, c;
 43 }ee[maxm];
 44 struct Edge
 45 {
 46     Edge *next, *rev;
 47     int from, to, cap, cost;
 48 }*last[maxn], e[maxm], *ecnt = e, *cur[maxn], *prev[maxn];
 49 inline void link(R int a, R int b, R int w, R int c)
 50 {
 51     *++ecnt = (Edge) {last[a], ecnt + 1, a, b, w, c}; last[a] = ecnt;
 52     *++ecnt = (Edge) {last[b], ecnt - 1, b, a, 0, -c}; last[b] = ecnt;
 53 }
 54 #define inf 0x7fffffff
 55 int s, t, dep[maxn], ans, d[maxn];
 56 std::queue<int> q;
 57 inline bool bfs()
 58 {
 59     memset(dep, -1, sizeof (dep));
 60     dep[t] = 0; q.push(t);
 61     while (!q.empty())
 62     {
 63         R int now = q.front(); q.pop();
 64         for (R Edge *iter = last[now]; iter; iter = iter -> next)
 65         {
 66             R int pre = iter -> to;
 67             if (iter -> rev -> cap && dep[pre] == -1)
 68             {
 69                 dep[pre] = dep[now] + 1;
 70                 q.push(pre);
 71             }
 72         }
 73     }
 74     return dep[s] != -1;
 75 }
 76 int dfs(R int x, R int f)
 77 {
 78     if (x == t) return f;
 79     R int used = 0;
 80     for (R Edge* &iter = cur[x]; iter; iter = iter -> next)
 81     {
 82         R int pre = iter -> to;
 83         if (iter -> cap && dep[x] == dep[pre] + 1)
 84         {
 85             R int v = dfs(pre, dmin(iter -> cap, f - used));
 86             iter -> cap -= v;
 87             iter -> rev -> cap += v;
 88             used += v;
 89             if (f == used) return f;
 90         }
 91     }
 92     if (!used) dep[x] = -1;
 93     return used;
 94 }
 95 inline void dinic()
 96 {
 97     while (bfs())
 98     {
 99         memcpy(cur, last, sizeof last);
100         ans += dfs(s, inf);
101     }
102 }
103 bool inq[maxn];
104 inline bool spfa()
105 {
106     for (R int i = 1; i <= t; ++i) d[i] = inf;
107     q.push(s);
108     while (!q.empty())
109     {
110         R int now = q.front(); q.pop(); inq[now] = 0;
111         for (R Edge *iter = last[now]; iter; iter = iter -> next)
112         {
113             R int pre = iter -> to;
114             if (iter -> cap && d[pre] > d[now] + iter -> cost)
115             {
116                 d[pre] = d[now] + iter -> cost;
117                 prev[pre] = iter;
118                 if (!inq[pre])
119                 {
120                     q.push(pre);
121                     inq[pre] = 1;
122                 }
123             }
124         }
125     }
126     return d[t] != inf;
127 }
128 inline void mcmf()
129 {
130     R int x = inf;
131     for (R Edge *iter = prev[t]; iter; iter = prev[iter -> from])
132         cmin(x, iter -> cap);
133     for (R Edge *iter = prev[t]; iter; iter = prev[iter -> from])
134     {
135         iter -> cap -= x;
136         iter -> rev -> cap += x;
137         ans += x * iter -> cost;
138     }
139 }
140 int main()
141 {
142 //    setfile();
143     R int n = F(), m = F(), k = F();
144     for (R int i = 1; i <= m; ++i)
145     {
146         R int a = F(), b = F(), w = F(), c = F();
147         link(a, b, w, 0); ee[i] = (edge) {a, b, w, c};
148     }
149     s = 1; t = n;
150     dinic();
151     printf("%d ", ans );
152     ans = 0;
153     for (R int i = 1; i <= m; ++i) link(ee[i].a, ee[i].b, inf, ee[i].c);
154     s = 0; t = n;
155     link(s, 1, k, 0);
156     while (spfa()) mcmf();
157     printf("%d\n", ans );
158     return 0;
159 }
时间: 2024-08-13 05:21:43

【BZOJ1834】 [ZJOI2010]network 网络扩容的相关文章

bzoj1834: [ZJOI2010]network 网络扩容

这道题分为俩步,第一是求最大流,第二是在第一问的残量网络上求最小费用流. 建图时俩个点直接连2条边,一条容量为f[i],费用为0,另一条容量为inf,费用为c[i].这样就可以跑俩个算法了 第二问设一个虚拟源点S与1连容量为k,费用为0的边,n与一个虚拟汇点T连容量为k,费用为0的边.这样一直跑,最后只会增加k的流量. 记住bool一定要用true和false,用0和1tle了..不知道为啥,但一定要记住 #include<cstdio> #include<algorithm> #

【最大流】【费用流】bzoj1834 [ZJOI2010]network 网络扩容

引用题解: 最大流+费用流. 第一问最大流即可. 第二问为“最小费用最大流”. 由题意,这一问的可转化为在上一问的“残量网络”上,扩大一些边的容量,使能从新的图中的最大流为k. 那么易得:对于还有剩余流量的边,走过他们的费用为0.而“增加流量”可变为:对残留网络上的每一条边建一条容量是∞费用是w的边.这表示从这些边走,每一流量的费用为w,这就符合题意了. 最后建一个超级源点,从超级源向1建一条容量为k,费用为0的边,就可进行最小费用最大流算法. #include<cstdio> #includ

bzoj1834: [ZJOI2010]network 网络扩容

努力看了很久样例一直过不了...然后各种输出中间过程啊巴拉巴拉弄了1h,没办法了...然后突然想到啊原来的边可以用啊为什么不用...于是A了...感人肺腑 #include<cstdio> #include<cstring> #include<queue> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n

bzoj 1834: [ZJOI2010]network 网络扩容 -- 最大流+费用流

1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec  Memory Limit: 64 MB Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. Input 输入文件的第一行包含三个整数N,M,K,表示有向图的点数.边数以及所需要增加的流量. 接下来的M行每行包含四个整数u,v,C,W,表示一

【bzoj1834】[ZJOI2010]network 网络扩容 最大流+最小费用流

题目描述 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. 输入 输入文件的第一行包含三个整数N,M,K,表示有向图的点数.边数以及所需要增加的流量. 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边. 输出 输出文件一行包含两个整数,分别表示问题1和问题2的答案. 样例输入 5 8 2 1 2 5 8 2 5 9

【BZOJ1834】network 网络扩容(最大流,费用流)

题意:给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的最小扩容费用. 30%的数据中,N<=100 100%的数据中,N<=1000,M<=5000,K<=10 思路:RYZ作业 第一问最大流即可 第二问网上很多题解都是在第一问的残余网络上构图,但是根本不需要 考虑边(x,y,z,w) 有容量为z,费用为0的免费流量,有容量为INF,费用为w的扩容付费流

【BZOJ】1834: [ZJOI2010]network 网络扩容(最大流+费用流)

我又思考人生了T_T,nd的数组开小了,一直wa,调了一个小时才发现啊!!!!!我一直以为我的isap错了T_T,可是完全没错啊!!!! 这题其实第一个问很简单,跑一次最大流即可.第二个问就是在跑完最大流的残量网络上每条边都扩充容量为oo,费用为边的费用,然后设个超级源连一条容量为k的边到点1,再跑一次费用流即可. 理由很简单,自己想,我就不说了. #include <cstdio> #include <cstring> #include <cmath> #includ

【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 Inpu

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 Inpu