• 网络流建模专题


    struct DI {
        ll n, m, S, T;
        ll h[N], ne[M], to[M], f[M], idx;
        void add(ll u, ll v, ll w) {
            ne[idx] = h[u], to[idx] = v, f[idx] = w, h[u] = idx++;
            ne[idx] = h[v], to[idx] = u, f[idx] = 0, h[v] = idx++;
        }
        queue<ll> q;
        ll d[N];
        ll cur[N];
        void init() {
            for (int i = 0; i <= idx; i ++)h[i] = -1;
            idx = 0;
        }
        bool bfs() {
            while (!q.empty()) q.pop();
            q.push(S);
            memset(d, -1, sizeof d);  // d数组是深度,防止绕进环中去。
            d[S] = 0;
            cur[S] = h[S];  //必然第一个弧就是,但是容易忘。
            while (!q.empty()) {
                auto u = q.front();
                q.pop();
                for (ll i = h[u]; ~i; i = ne[i]) {
                    ll v = to[i];
                    if (f[i] && d[v] == -1) {  //找增广路,所以必须f[i] > 0
                        d[v] = 1 + d[u];
                        cur[v] = h[v];  //只会遍历一次。
                        if (v == T) return 1;
                        q.push(v);
                    }
                }
            }
            return 0;
        }
        ll dfs(ll u, ll limit) {
            if (u == T) return limit;  //容易忘。终点直接返回
            ll flow = 0;               //点流向后面的。
            for (ll i = cur[u]; ~i && flow < limit;
                 i = ne[i]) {  //从当前弧开始,如果之前
                ll v = to[i];
                cur[u] = i;  //回溯到u点之前,然后又到了u点,没必要从头开始了。
                if (d[v] == d[u] + 1 && f[i]) {  // d是按照层数走,f必须大于0。
                    ll t = dfs(v, min(f[i], limit - flow));  // t是走向出去的流量。
                    if (t <= 0) d[v] = -1;  //一滴也没有了,点就可以删掉了。
                    f[i] -= t;
                    f[i ^ 1] += t;  //更新残留网络。
                    flow += t;  //当前总的流向后面的加上当前v流向后面的。
                }
            }
            return flow;
        }
        ll dinic() {
            ll ret = 0, flow;
            while (bfs()) {
                while (flow = dfs(S, inf)) ret += flow;
            }
            //init();
            return ret;
        }
        void makemap() {
            init();
            scanf("%d", &n);
            S = 0;
            T = N-1;
            for (int i = 1; i <= n * 2; i ++)add(S, i, 1);
            for (int i = 1; i <= 2 * n; i ++) {
                int u, v;
                scanf("%d%d", &u, &v);
                u += 3*n;
                v += 3*n;
                add(i, u, 1);
                add(i, v, 1);
                
            }
            for (int i = 1; i <= n; i ++) {
                add(i + 3 * n, T, 2);
            }
        }
    }dinic;
    
    
    • P2754 [CTSC1999]家园 / 星际转移问题
      按照时间建立分层图建模,注意飞船转移的时候当飞船返回也要建立一条边。

    • P2526 [SHOI2001]小狗散步
      发现是一个二分图的关键在于,是否能找到他们是一一对应的关系,这个小狗他每次只出去一个经典,就很无语。

    • P2057 [SHOI2007]善意的投票 / [JLOI2010]冠军调查
      冲突模型最小割,睡觉不睡觉一定会分成两个集合,然后好朋友们之间流量是1,所以建立双向边跑最大流得到最小割,就是把他们分成睡觉和不睡觉最小冲突的分法。

    • [TJOI2013]攻击装置
      经中之典的建模,一些关系不能冲突,求互不冲突最大数量,最大独立集,就是所有点数量减去最大匹配。

    • Penguins LightOJ - 1154-vj
      拆点,会发现,跳跃之间流量要赋成正无穷,所以如果要限制跳跃次数,就应该把一个冰拆成两层,用 (limit) 跳跃次数作为流量从底层跳到高层,然后再跳向其他的底层,然后枚举汇点,注意汇点连接的是底层

    • P1251 餐巾计划问题
      如果题目中要求每天都要满足条件,类似的,那么就可以设为将每个要满足的和汇点连边,容量设为应满足的条件。

    • P1345 [USACO5.4]奶牛的电信Telecowmunication
      经中之典最小割,如果要求删去最小数量边,好求。如果要求删去数量的点,那么就要使得每个点拆成出度和入度,之间的流量限制为 (1), 然后就可以出度点连接入度点了,权值设为正无穷,注意不要另设一个源汇点,因为如果求最小割,还是点之间的,想想就知道不行。

    • HDU 3605
      经中之典状态压缩,(n) 太多了没想到 (m) 很小,然后就可以多记录状态了。

    • P1361 小M的作物
      经中之典最小割模型,种两种地方,有不同的收获,并且组合种某种地方也有格外收获,会发现如果从 (A)(B) 就是最小割模型。

    • P4843 清理雪道
      发现,题目要求每条边必须走过,那么所以一定是所有边流量下界为1,然后流量上界为inf,所以就是建好无源汇上下界可行流,然后搞有源汇上下界最小流。

    • P4043 [AHOI2014/JSOI2014]支线剧情
      经典上下界最小费用可行流,就是定好上下界和费用,然后返回的时候连反向正无穷边。注意,得到新图后,最小费用是先计算好下界流量乘以相应费用,然后在计算附加图的最小费用。

    • P3980 [NOI2008] 志愿者招募
      经典上下界最小费用可行流,但是这个没算原图的流量下界乘费用,因为反边的流量下界为0。

    • P4311 士兵占领
      经典网格图,然后就是最开始的想法是,作为无源汇可行流来解,即只有行的入点出点,列的入点出点,网格上的点,但是这样边和点数量过多。可是如果想象成类似二分图,把行和列拿出来,然后虚拟源点连接行,然后列连接虚拟汇点,然后行和列之间就可以连边,规定好流量上下界即可解决。

    • P4553 80人环游世界
      简单上下界费用流建模。景点国家的出入点决定到这个国家几个人,然后源点连出流量为人数的点到一个小源点,然后从小源点连向每个景点,然后景点之间机票可以连边,从景点的出点连向景点的入点。

    • P1344 [USACO4.4]追查坏牛奶Pollutant Control
      最小割神仙题目,不仅让求最小的割,并且求得的是边的割集的最小权值和,一种神仙做法是,将每个边权转化为, (w = x imes C + y),其中 (sum y < C),所以就是 (y) 就是1,意义是一条边,然后最后求得答案,割的数量就是 (maxflow mod C),最小边权和就是 (frac{maxflow}{C}).

  • 相关阅读:
    博客转移到cnblogs
    mmsplayer for ios 支持iphone ,ipad,ipod touch 版本已经完成。
    mmsplayer for ios v1.0
    无ldf文件情况下恢复数据库数据纪实
    我的Blog页面设计
    使用C#生成静态页面
    C++开发工具
    使用JNDI来读取Notes通讯录中的数据
    关于Char与string
    JavaScript站点荟萃
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/15137335.html
Copyright © 2020-2023  润新知