zoukankan      html  css  js  c++  java
  • bzoj2502【有上下界的最大流】

    2502: 清理雪道

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 834  Solved: 442
    [Submit][Status][Discuss]

    Description

           滑雪场坐落在FJ省西北部的若干座山上。
    从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向。
    你的团队负责每周定时清理雪道。你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部。从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道。
    由于每次飞行的耗费是固定的,为了最小化耗费,你想知道如何用最少的飞行次数才能完成清理雪道的任务。
     

    Input

     
    输入文件的第一行包含一个整数n (2 <= n <= 100) – 代表滑雪场的地点的数量。接下来的n行,描述1~n号地点出发的斜坡,第i行的第一个数为mi (0 <= mi < n) ,后面共有mi个整数,由空格隔开,每个整数aij互不相同,代表从地点i下降到地点aij的斜坡。每个地点至少有一个斜坡与之相连。

    Output

     
           输出文件的第一行是一个整数k – 直升飞机的最少飞行次数。
     

    Sample Input

    8
    1 3
    1 7
    2 4 5
    1 8
    1 8
    0
    2 6 5
    0

    Sample Output

    4

    HINT

     

    Source

    2011福建集训

    这道题网上所有的解答都是最小流 但是我搞到了一个有上下界的最大流的做法 不知道对不对 求大家来批判

    原始建图:

    首先设立虚拟源汇S、T,S向每个节点u连一条容量为1的边,下界为0。因为每个点最多空降一次。

    每个出度为0的点向汇点连边,容量为+∞

    设fx=S -> u 的流量 fe=u -> v 的流量 fE=u->t的流量

    设对于点u,流进来的流量为fe1,流出为fe2

    由流量平衡得:fe1+fx=fe2+fE

    设gx=出度-fx(fx<=出度) ->gx>=0(这里因为从这里滑到终点的次数不会比出度多)

     gE=入度-fE(fE<=入度)->gE>=0(同上)

     ge1=fe1-1 ge2=fe2-1

     由fe1+fe=fe2+fE推出ge1+1+出度-gx=ge2+1+入度-fE

     ge1+入度+出度-gx=ge2+入度+出度-gE

     ge1-gx=ge2-gE ge1+gE=ge2+gx

     这个东西满足流量平衡 然后我们跑一遍有上下界的最大流就可以了。

     代码未填坑

     这是最小流的代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1010, inf = 1 << 29;
    struct edge {
        int nxt, to, f;
    } e[100010];
    int n, cnt = 1, SS, TT, ans, T, tot;
    int head[N], d[N], q[N], in[N], iter[N];
    void link(int u, int v, int f)
    {
        e[++cnt].nxt = head[u];
        head[u] = cnt;
        e[cnt].to = v;
        e[cnt].f = f;
    }
    void ins(int u, int v, int f) { link(u, v, f); link(v, u, 0); }
    bool bfs()
    {
        int l = 1, r = 0;
        memset(d, 0, sizeof(d));
        q[++r] = SS; d[SS] = 1;
        while(l <= r) 
        {
            int u = q[l++];
            for(int i = head[u]; i; i = e[i].nxt) if(e[i].f && !d[e[i].to])
            {
                d[e[i].to] = d[u] + 1;
                q[++r] = e[i].to;
            }
        }
        return d[TT] > 0;
    }
    int dfs(int u, int delta)
    {
        if(u == TT) return delta;
        int ret = 0;
        for(int &i = iter[u]; i && delta; i = e[i].nxt) if(e[i].f && d[e[i].to] == d[u] + 1)
        {
            int x = dfs(e[i].to, min(delta, e[i].f));
            e[i].f -= x; e[i ^ 1].f += x;
            delta -= x; ret += x;
        }
        return ret;
    }
    void dinic()
    {
        while(bfs())
        {
            for(int i = 0; i <= TT; ++i) iter[i] = head[i];
            ans += dfs(SS, inf);
        }
    }
    int main()
    {
        scanf("%d", &n);
        T = n + 1; SS = n + 2; TT = n + 3; 
        for(int i = 1; i <= n; ++i)
        {
            int m;
            ins(0, i, inf); 
            scanf("%d", &m);
            if(!m) ins(i, T, inf);
            for(int j = 1; j <= m; ++j)
            {
                int u; scanf("%d", &u); ++tot;
                --in[i]; ++in[u]; 
                ins(i, u, inf);
            }
        }
        for(int i = 0; i <= T; ++i)
        {
            if(in[i] > 0) ins(SS, i, in[i]);
            else ins(i, TT, -in[i]);
        }
        dinic();
        ins(n + 1, 0, inf);
        dinic();
        printf("%d
    ", inf - e[cnt ^ 1].f);
        return 0;
    }
  • 相关阅读:
    Beetl模板 [记录]
    wx 小程序开发 [记录]
    高德定位获取省市区[记录]
    vue 学习记录 [记录]
    正则表达+验证 [记录]
    倒计时60s短信 [记录]
    @media [记录]
    JSON + Ajax [记录]
    Webstorm [记录]
    JQ 组合代码 [记录]
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6624018.html
Copyright © 2011-2022 走看看