首页 > 代码库 > BZOJ3438 小M的作物

BZOJ3438 小M的作物

叫什么"最大权闭合图" -- from PoPoQQQ

首先建立源点汇点S、T表示种在a,b两片土里,流量为收益。

然后每次读到一个集合的时候,新建两个虚拟节点si、ti,表示都种在a,b里的收益

S向si连边,ti向T连边,流量为收益,然后si、ti向集合内所有点连边。

之后跑一边最大流,ans = 总收益 - 最小割

 

  1 /**************************************************************  2     Problem: 3438  3     User: rausen  4     Language: C++  5     Result: Accepted  6     Time:2664 ms  7     Memory:24280 kb  8 ****************************************************************/  9   10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13   14 using namespace std; 15 const int inf = (int) 1e9; 16 const int N = 3005; 17 const int M = 2000005; 18   19 struct edges{ 20     int next, to, f; 21     edges() {} 22     edges(int _n, int _t, int _f) : next(_n), to(_t), f(_f) {} 23 } e[M]; 24   25 int n, m; 26 int cnt, ans, S, T; 27 int first[N], tot = 1; 28 int q[N], d[N]; 29   30 inline int read() { 31     int x = 0; 32     char ch = getchar(); 33     while (ch < 0 || 9 < ch) 34         ch = getchar(); 35     while (0 <= ch && ch <= 9) { 36         x = x * 10 + ch - 0; 37         ch = getchar(); 38     } 39     return x; 40 } 41   42 inline void Add_Edges(int x, int y, int z){ 43     e[++tot] = edges(first[x], y, z), first[x] = tot; 44     e[++tot] = edges(first[y], x, 0), first[y] = tot; 45 } 46     47 bool bfs(){ 48     memset(d, 0, sizeof(d)); 49     q[1] = S, d[S] = 1; 50     int l = 0, r = 1, x, y; 51     while (l < r){ 52         ++l; 53         for (x = first[q[l]]; x; x = e[x].next){ 54             y = e[x].to; 55             if (!d[y] && e[x].f) 56                 q[++r] = y, d[y] = d[q[l]] + 1; 57         } 58     } 59     return d[T]; 60 } 61     62 int dinic(int p, int limit){ 63     if (p == T || !limit) return limit; 64     int x, y, tmp, rest = limit; 65     for (x = first[p]; x; x = e[x].next){ 66         y = e[x].to; 67         if (d[y] == d[p] + 1 && e[x].f && rest){ 68             tmp = dinic(y, min(rest, e[x].f)); 69             rest -= tmp; 70             e[x].f -= tmp, e[x ^ 1].f += tmp; 71             if (!rest) return limit; 72         } 73     } 74     if (limit == rest) d[p] = 0; 75     return limit - rest; 76 } 77     78 int Dinic(){ 79     int res = 0, x; 80     while (bfs()) 81         res += dinic(S, inf); 82     return res; 83 } 84   85 int main() { 86     int i, j, x, y, z; 87     n = cnt = read(), S = 3001, T = 3002; 88     for (i = 1; i <= n; ++i) { 89         ans += (x = read()); 90         Add_Edges(S, i, x); 91     } 92     for (i = 1; i <= n; ++i) { 93         ans += (x = read()); 94         Add_Edges(i, T, x); 95     } 96     m = read(); 97     for (i = 1; i <= m; ++i) { 98         j = read(), x = read(), y = read(); 99         ans += x + y;100         Add_Edges(S, ++cnt, x), Add_Edges(++cnt, T, y);101         while (j--) {102             z = read();103             Add_Edges(z, cnt, inf), Add_Edges(cnt - 1, z, inf);104         }105     }106     printf("%d\n", ans - Dinic());107     return 0;108 }
View Code

 

BZOJ3438 小M的作物