• bzoj3550


    费用流+线性规划

    搞了很长时间。。。

    我们可以设立式子,a[1]+a[2]+a[3]+...+a[n]<=k , ... , a[2 * n + 1]+ ... +a[3*n]<=k

    a是指该位有没有选

    那么我们添加一个辅助变量f

    a[1]+a[2]+a[3]+...+a[n]+f[1]=k,

    ...

    a[2*n+1]+...+a[3*n]+f[2*n+1]=k

    我们就得到了2n+1个式子

    然后我们添加两个式子a(0):0=0 a(2*n+2):0=0

    然后差分得到2n+2个式子,后一个式子减前一个式子

    0:a[1]+a[2]+...+a[n]+f[1]=k

    1:a[2]+...+a[n+1]+f[2]-a[1]-...-a[n]-f[1]=0->a[n+1]+f[2]-a[1]-f[1]=0

    2:a[n+2]+f[3]-a[2]-f[2]=0

    ...

    2n+1:a[3*n]+f[2*n+1]-a[2*n]-f[2*n]

    2n+2:a[2n+1]+...+a[3*n]+f[2*n+1]=k

    然后这个式子很像网络流的流量平衡,于是这样建图,正对负,负对正,因为第0项是a[1]+...+a[n],所以0->[1,n],因为都是这样形式的a[n+1]+f[2]-a[1]-f[1],-a[1]和+a[1]对应,因为a∈[0,1],所以流量为1,a[i]=1是指选了a[i],所以费用为a[i]

    i-1->i,因为相邻两项-f[i],+f[i],f[i]∈[0,k],因为是辅助变量,所以什么都没有对应,流量为k,费用为0

    后面类似 然后就建好图了 设立源汇和1n相连,流量为k 感觉理解不够深刻 碰见这种序列+限制的题可以用费用流做,先把限制代数化,然后-+连边,一般还会相邻的点之间连边,这样可以解决一些序列的问题,以后碰见再做

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1010, inf = 0x3f3f3f3f;
    struct edge {
        int nxt, to, f, c;
    } e[N * 50];
    int n, m, k, source, sink, tot, cnt = 1, sum;
    int a[N], head[N], d[N], pree[N], prev[N], vis[N], live[N], dead[N], day[N], c[N], l[N], p[N];
    inline void link(int u, int v, int f, int c)
    {
        e[++cnt].nxt = head[u];
        head[u] = cnt;
        e[cnt].f = f;
        e[cnt].to = v;
        e[cnt].c = c;
    }
    inline void insert(int u, int v, int f, int c)
    {
        link(u, v, f, c);
        link(v, u, 0, -c);
    }
    bool spfa()
    {
        memset(d, -1, sizeof(d));
        d[source] = 0;
        queue<int> q;
        q.push(source);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for(int i = head[u]; i; i = e[i].nxt) if(e[i].f && (d[e[i].to] < d[u] + e[i].c || d[e[i].to] == -1))
            {
                pree[e[i].to] = i;
                prev[e[i].to] = u;
                d[e[i].to] = d[u] + e[i].c;
                if(vis[e[i].to] == 0)
                {
                    q.push(e[i].to);
                    vis[e[i].to] = 1;
                }
            }
        }
        return d[sink] != -1; 
    }
    inline int Edmonds_Karp()
    {
        int ans = 0;
        while(spfa())
        {
            int now = sink, delta = inf;
            while(now != source)
            {
                delta = min(delta, e[pree[now]].f);
                now = prev[now];
            }
            now = sink;
            while(now != source)
            {
                e[pree[now]].f -= delta;
                e[pree[now] ^ 1].f += delta; 
                now = prev[now];
            }
            ans += delta * d[sink];
        }
        return ans;
    }
    int main()
    {
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= 3 * n; ++i) scanf("%d", &a[i]);
        source = 2 * n + 2;
        sink = 2 * n + 3;
        int s = 0, t = 2 * n + 1; 
        insert(source, s, k, 0);
        insert(t, sink, k, 0);
        sink = 2 * n + 1;
        for(int i = 1; i <= n; ++i) insert(s, i, 1, a[i]);
        for(int i = 1; i <= 2 * n + 1; ++i) insert(i - 1, i, k, 0);
        for(int i = n + 1; i <= 2 * n; ++i) insert(i, t, 1, a[i + n]);
        for(int i = n + 1; i <= 2 * n; ++i) insert(i - n, i, 1, a[i]);    
    
    /*    for(int i = 1; i <= 2 * n + 1; ++i) insert(i - 1, i, k, 0);
        for(int i = 1; i <= n; ++i) 
        {
            insert(s, i, 1, a[i]);
            insert(i, i + n, 1, a[i + n]);
            insert(i + n, t, 1, a[i + 2 * n]);
        } */
        printf("%d
    ", Edmonds_Karp());
        return 0;
    } 
    View Code
  • 相关阅读:
    专家教你应对小孩鼻血不止
    爸爸去哪?
    Windows server 2008 R2 + IIS7.5,ASP网站设置
    请把这十个生命气质传给孩子
    zoj 2071 Technology Trader 最大权闭合子图
    TJU 2944 Mussy Paper 最大权闭合子图
    poj 1222 EXTENDED LIGHTS OUT 高斯消元
    codeforces 383C Propagating tree 线段树
    ubuntu 安装qq
    Kafka Manager 监控
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7350751.html
Copyright © 2020-2023  润新知