zoukankan      html  css  js  c++  java
  • 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
    ", ans - Dinic());
    107     return 0;
    108 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    Windows Phone 一步一步从入门到精通
    备忘录模式(Memento)
    开放封闭原则(OCP)
    建造者模式(Bulider)
    原型模式(Prototype)
    Windows Workflow Foundation(WF) 一步一步从入门到精通
    模板方法模式
    代理模式(Proxy)
    装饰模式(Decorator)
    迪米特法则(LoD)最少知识原则
  • 原文地址:https://www.cnblogs.com/rausen/p/4133449.html
Copyright © 2011-2022 走看看