费用流

和3280很像,先建出上下界模型,然后转为普通费用流模型

s->1 flow=inf, c = f

s->i+n flow=x,c=0;

i->t,flow=x,c=0

i->i+1 flow=inf, c=0;

i+n->i+n+1,flow=inf,c=0

i->i+a+1,i->i+b+1,flow=inf,c=fa/fb

i表示到第i天干净的抹布

i+n表示第i天不干净的抹布

i->i+n上下界都为x,对于上下界的处理只需要连3条边就行了,对于边(u,v),从s->v,flow=下界,c=(u,v)的费用,u->t,flow=下界,c=0,u->v,flow=上界-下界,c=(u,v)的费用

bzoj1221_#includebzoj1221_网络流_02
#include<bits/stdc++.h>
using namespace std;
const int N = 2010, inf = 1 << 29;
struct edge {
    int nxt, to, f, c;
} e[N * 40];
int n, m, source, sink, cnt = 1, a, b, f, fa, fb;
int head[N], d[N], pree[N], prev[N], vis[N];
void link(int u, int v, int f, int c)
{
    e[++cnt].nxt = head[u];
    head[u] = cnt;
    e[cnt].to = v;
    e[cnt].f = f;
    e[cnt].c = c;
}
void insert(int u, int v, int f, int c)
{
    link(u, v, f, c);
    link(v, u, 0, -c);
}
bool spfa()
{
    queue<int> q;
    q.push(source);
    memset(d, -1, sizeof(d));
    d[source] = 0;
    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))
        {
            d[e[i].to] = d[u] + e[i].c;
            pree[e[i].to] = i;
            prev[e[i].to] = u;
            if(vis[e[i].to] == 0)
            {
                vis[e[i].to] = 1;
                q.push(e[i].to); 
            }
        }
    }
    return d[sink] != -1;
}
inline int Edmonds_Karp()
{
    int ret = 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];
        }
        ret += delta * d[sink];
    }
    return ret;
}
int main()
{
    scanf("%d%d%d%d%d%d", &n, &a, &b, &f, &fa, &fb);
    sink = 2 * n + 1;
    insert(source, 1, inf, f);
    for(int i = 1; i <= n; ++i) 
    {
        int x;
        scanf("%d", &x);
        insert(source, i + n, x, 0);
        insert(i, sink, x, 0);
        if(i < n) 
        {
            insert(i, i + 1, inf, 0);
            insert(i + n, i + n + 1, inf, 0);
        }
        if(i + a + 1 <= n) insert(i + n, i + a + 1, inf, fa);
        if(i + b + 1 <= n) insert(i + n, i + b + 1, inf, fb);
    }
    printf("%d\n", Edmonds_Karp());
    return 0;
}
View Code