bzoj2245

费用流

比较裸的费用流,唯一的问题在于费用,由于费用是单调递增的,那么我们可以拆边,源点连向每个人source->i,f=ti-ti-1,c=w,这样就好了,因为费用递增,所以符合费用流的贪心思想,肯定先选小的费用,再走大的费用

#include<bits/stdc++.h>
using namespace std;
const int N = 610, inf = 0x3f3f3f3f;
struct edge {
    int nxt, to, f;
    long long c;
} e[N * N << 2];
int n, m, k, source, sink, tot, cnt = 1, sum;
int a[N][N], head[N], pree[N], prev[N], t[N], vis[N], w[N], day[N], c[N], l[N], p[N];
long long d[N];
inline void link(int u, int v, int f, long long 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 long long Edmonds_Karp()
{
    long long 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 += (long long)delta * d[sink];
    } 
    return ans;
}
int main()
{
    cin >> m >> n;
    source = 0;
    sink = m + n + 1;
    for(int i = 1; i <= n; ++i) 
    {
        int c;
        scanf("%d", &c);
        insert(i + m, sink, c, 0);
    }    
    for(int i = 1; i <= m; ++i)
        for(int j = 1; j <= n; ++j) 
        {
            int x;
            scanf("%d", &x);
            if(x == 1) insert(i, j + m, inf, 0);
        }
    for(int i = 1; i <= m; ++i)
    {
        int s;
        scanf("%d", &s);
        for(int j = 1; j <= s; ++j) scanf("%d", &t[j]);
        t[++s] = inf;
        for(int j = 1; j <= s; ++j)
        {
            long long w;
            scanf("%lld", &w);
            insert(source, i, t[j] - t[j - 1], w);
        }
    }    
    cout << Edmonds_Karp();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/19992147orz/p/7507496.html