zoukankan      html  css  js  c++  java
  • P2488 [SDOI2011]工作安排 费用流

    (color{#0066ff}{ 题目描述 })

    你的任务是制定出一个产品的分配方案,使得订单条件被满足,并且所有员工的愤怒值之和最小。由于我们并不想使用Special Judge,也为了使选手有更多的时间研究其他两道题目,你只需要输出最小的愤怒值之和就可以了。

    (color{#0066ff}{输入格式})

    (color{#0066ff}{输出格式})

    仅输出一个整数,表示最小的愤怒值之和。

    (color{#0066ff}{输入样例})

    2 3
    2 2 2
    1 1 0
    0 0 1
    1
    2
    1 10
    1
    2
    1 6
    

    (color{#0066ff}{输出样例})

    24
    

    (color{#0066ff}{数据范围与提示})

    (color{#0066ff}{ 题解 })

    显然是个费用流

    考虑怎么建边

    愤怒值对于每个员工完成工作的数量来分段

    完成工作数量? 这不就是从员工流出去多少流吗

    所以,从S向员工,连多条边,每条边的容量为每段的长

    这样愤怒值的问题就解决了

    注意,每个任务不止完成一次

    所以员工向任务连容量为inf的边,任务向T连容量为需要次数的边

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
        char ch; LL x = 0, f = 1;
        while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
        for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
        return x * f;
    }
    const int maxn = 1e5;
    const LL inf = 999999999999999LL;
    struct node {
        int to;
        LL dis, can;
        node *nxt, *rev;
        node(int to = 0, LL dis = 0, LL can = 0, node *nxt = NULL)
            : to(to), dis(dis), can(can), nxt(nxt) {}
        void *operator new (size_t) {
            static node *S = NULL, *T = NULL;
            return (S == T) && (T = (S = new node[1024]) + 1024), S++;
        }
    };
    LL dis[maxn], change[maxn];
    node *head[maxn], *road[maxn];
    bool vis[maxn];
    bool f[505][505];
    int n, s, t, m;
    std::vector<LL> v[maxn], d[maxn];
    bool spfa() {
        for(int i = s; i <= t; i++) dis[i] = inf, change[i] = inf;
        std::queue<int> q;
        dis[s] = 0;
        q.push(s);
        while(!q.empty()) {
            int tp = q.front(); q.pop();
            vis[tp] = false;
            for(node *i = head[tp]; i; i = i->nxt) 
                if(dis[i->to] > dis[tp] + i->dis && i->can) {
                    dis[i->to] = dis[tp] + i->dis;
                    change[i->to] = std::min(change[tp], i->can);
                    road[i->to] = i;
                    if(!vis[i->to]) vis[i->to] = true, q.push(i->to);
                }
        }
        return change[t] != inf;
    }
    
    LL mcmf() {
        LL cost = 0;
        while(spfa()) {
            cost += change[t] * dis[t];
            for(int o = t; o != s; o = road[o]->rev->to) {
                road[o]->can -= change[t];
                road[o]->rev->can += change[t];
            }
        }
        return cost;
    }
    void add(int from, int to, LL dis, LL can) {
        head[from] = new node(to, dis, can, head[from]);
    }
    void link(int from, int to, LL dis, LL can) {
        add(from, to, dis, can);
        add(to, from, -dis, 0);
        head[from]->rev = head[to];
        head[to]->rev = head[from];
    }
    int main() {
        m = in(), n = in();
        t = m + n + 1, s = 0;
        for(int i = m + 1; i <= m + n; i++) link(i, t, 0, in());
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
                if(in()) link(i, m + j, 0, inf);
        for(int i = 1; i <= m; i++) {
            int k = in();
            v[i].push_back(0);
            for(int j = 1; j <= k; j++) v[i].push_back(in());
            v[i].push_back(inf);
            for(int j = 1; j <= k + 1; j++) d[i].push_back(in());
            for(int j = 0; j <= k; j++) link(s, i, d[i][j], v[i][j + 1] - v[i][j]);
        }
        printf("%lld", mcmf());
        return 0;
    }
    
  • 相关阅读:
    从底层来看Promise
    Promise初探
    时间复杂度和空间复杂度
    IDEA maven Run Maven 启动方式
    IDEA 运行maven工程报错:No goals have been specified for this build.....解决办法
    12.外键约束
    11.约束的概念及分类
    10.创建表-备注与创建表的细节说明。
    9.创建表-自增长(AUTO_INCREAMENT)
    8.创建表--主键的概念与应用
  • 原文地址:https://www.cnblogs.com/olinr/p/10357255.html
Copyright © 2011-2022 走看看