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;
    }
  • 相关阅读:
    Windows XP下 Android开发环境 搭建
    Android程序的入口点
    在eclipse里 新建android项目时 提示找不到proguard.cfg
    64位WIN7系统 下 搭建Android开发环境
    在eclipse里 新建android项目时 提示找不到proguard.cfg
    This Android SDK requires Android Developer Toolkit version 20.0.0 or above
    This Android SDK requires Android Developer Toolkit version 20.0.0 or above
    Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead
    Windows XP下 Android开发环境 搭建
    Android程序的入口点
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6624018.html
Copyright © 2011-2022 走看看