zoukankan      html  css  js  c++  java
  • ZOJ3229 Shoot the Bullet

    嘟嘟嘟


    有源有汇上下界网络流之最大流。


    这题建图其实不难,从(s)向每一天连容量为([0, D])的边,每一天向对应的女孩连容量为([L, R])的边,每一个女孩向汇点连容量为([G, INF])的边。
    然后转换成上下界网络流的图:建立附加源附加汇(S, T),计算每一个点的出入度之差后连边。这时候还要从(t)(s)连一条([0, INF])的边,形成循环流。
    然后从(S)(T)跑一边最大流,如果流满。则说明存在可行流,于是切掉(t)(s)的边,再从(s)(t)跑一边最大流。则答案就是第一次(s)(t)的流加上第二次的流。
    求第一次(s)(t)的流有一个技巧,因为已经连了(t)(s)的一条边,所以只要取反向边的流量的相反数即可。


    19.04.24更新
    在某篇博客上看到,可以不删边,再跑一遍(s, t)的最大流,那么答案就是这次的最大流!


    然后我因为数组开的过大(才$5e6$)在zoj上段错误了…… ```c++ #include #include #include #include #include #include #include #include #include #include using namespace std; #define enter puts("") #define space putchar(' ') #define Mem(a, x) memset(a, x, sizeof(a)) #define rg register typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 1505; const int maxe = 1e5 + 5; inline ll read() { ll ans = 0; char ch = getchar(), last = ' '; while(!isdigit(ch)) last = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); if(last == '-') ans = -ans; return ans; } inline void write(ll x) { if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar(x % 10 + '0'); }

    int n, m, s, t, S, T;

    struct Edge
    {
    int nxt, from, to, cap, flow;
    }e[maxe];
    int head[maxn], ecnt = -1;
    void addEdge(int x, int y, int w)
    {
    e[++ecnt] = (Edge){head[x], x, y, w, 0};
    head[x] = ecnt;
    e[++ecnt] = (Edge){head[y], y, x, 0, 0};
    head[y] = ecnt;
    }

    int dis[maxn];
    bool bfs(int s, int t)
    {
    Mem(dis, 0); dis[s] = 1;
    queue q; q.push(s);
    while(!q.empty())
    {
    int now = q.front(); q.pop();
    for(int i = head[now], v; i != -1; i = e[i].nxt)
    {
    if(!dis[v = e[i].to] && e[i].cap > e[i].flow)
    {
    dis[v] = dis[now] + 1;
    q.push(v);
    }
    }
    }
    return dis[t];
    }
    int cur[maxn];
    int dfs(int now, int _t, int res)
    {
    if(now == _t || res == 0) return res;
    int flow = 0, f;
    for(int& i = cur[now], v; i != -1; i = e[i].nxt)
    {
    if(dis[v = e[i].to] == dis[now] + 1 && (f = dfs(v, _t, min(res, e[i].cap - e[i].flow))) > 0)
    {
    e[i].flow += f; e[i ^ 1].flow -= f;
    flow += f; res -= f;
    if(res == 0) break;
    }
    }
    return flow;
    }

    int maxflow(int s, int t)
    {
    int flow = 0;
    while(bfs(s, t))
    {
    memcpy(cur, head, sizeof(head));
    flow += dfs(s, t, INF);
    }
    return flow;
    }

    int b[maxn][maxn], d[maxn];
    void init()
    {
    Mem(head, -1); ecnt = -1;
    Mem(d, 0); Mem(b, 0);
    s = 0, t = n + m + 1;
    S = t + 1; T = S + 1;
    }

    int st[maxn];
    void print()
    {
    for(int i = 1; i <= n; ++i)
    {
    int top = 0;
    for(int j = head[i], v; j != -1; j = e[j].nxt)
    {
    v = e[j].to;
    if(v > n && v <= n + m) //别忘了前向星是倒着存边
    st[++top] = e[j].flow + b[i][v - n];
    }
    while(top) write(st[top]), enter, top--;
    }
    }

    int main()
    {
    while(~scanf("%d%d", &n, &m))
    {
    init();
    for(int i = 1; i <= m; ++i)
    {
    int x = read();
    addEdge(i + n, t, INF - x);
    d[i + n] += x; d[t] -= x;
    }
    for(int i = 1; i <= n; ++i)
    {
    int C = read(), D = read();
    addEdge(s, i, D);
    //d[s] += D; d[i] -= D; //最小流量为0,所以不加
    for(int j = 1; j <= C; ++j)
    {
    int id = read() + 1, L = read(), R = read();
    b[i][id] = L;
    addEdge(i, id + n, R - L);
    d[i] += L; d[id + n] -= L;
    }
    }
    int tot = 0;
    for(int i = 0; i <= t; ++i)
    if(d[i] < 0) addEdge(S, i, -d[i]);
    else addEdge(i, T, d[i]), tot += d[i];
    addEdge(t, s, INF);
    if(maxflow(S, T) < tot) {puts("-1 "); continue;}
    int tp = -e[ecnt].flow; e[ecnt].flow = e[ecnt].cap; // 相当于删去
    //上面这一行可以不用,这样答案直接就是maxflow(s, t)
    write(tp + maxflow(s, t)), enter;
    print(); enter;
    }
    return 0;
    }

  • 相关阅读:
    netcore 开发问题整理(图片地址)
    netcore 开发问题整理(下拉框)
    C# 请求网址中汉字的编码转换
    C# 时间戳
    c# 判断指定文件是否存在
    js数组常用方法整理
    服务器断电 Mysql启动失败
    Bean初始化之postProcessBeforeInitialization、afterPropertiesSet、init-method、postProcessAfterInitialization等方法的加载
    Java多线程基础
    Mysql多字段order by用法
  • 原文地址:https://www.cnblogs.com/mrclr/p/10102050.html
Copyright © 2011-2022 走看看