Modular Production Line (MCMF)

Modular Production Line

\[ Time Limit: 1000ms\quad Memory Limit: 65536kB \]

题意

给出 \(N\) 种零件,现在你可以用连续的一些零件组装成为一个产品,组装完你可以获得 \(w\) 的价值,要求每种零件最多使用 \(K\) 次并且每一个产品只能生产一个。问你最多可以获得的价值是多少。

思路

由于给出的 \(N\) 很大, \(M\)很小,那么显然,很多点都是没有用的,那么我们就可以将他们舍弃掉,只使用出现的点,那么可以考虑到离散化。

  • 对于给出的每一个区间 \(\left[u, v\right]\) 内的零件,我们可以从 \(u\)\(v+1\) 建一条流量为\(1\),费用为 \(-w\) 的边,表示制作了这一个产品的情况。
  • 对于全部的点,我们可以建一条从 \(i\)\(i+1\) 的边,表示第 \(i\) 个零件不使用的情况。
  • 对于超级源点和超级汇点,我们建一条从超级源点到第一个点,流量为 \(K\),费用为 \(0\) 的边,在建一条从最后一个点到超级汇点,流量为 \(K\),费用为 \(0\) 的边,这是为了防止任意一种零件使用次数超过 \(K\),所以从一开始就限制了流量。

最后跑最小费用最大流,算出的答案的绝对值就是要求的。

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pii        pair<int, int>
#define  INOPEN     freopen("in.txt", "r", stdin)
#define  OUTOPEN    freopen("out.txt", "w", stdout)

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 5e2 + 10;
const int    maxm = 1e4 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m, k;
int cas, tol, T;

struct Node{
    int u, v;
    int w, val;
    int next;
} node[maxm];
int head[maxn];
int pre[maxn], dis[maxn], cap[maxn], vis[maxn];

void addnode(int u, int v, int w, int val) {
    node[tol].u = u;
    node[tol].v = v;
    node[tol].w = w;
    node[tol].val = val;
    node[tol].next = head[u];
    head[u] = tol++;
}

bool spfa(int src, int des, int &flow, int &cost) {
    mes(pre, 0), mes(dis, inf), mes(cap, 0), mes(vis, false);
    queue<int> q;
    while(!q.empty())   q.pop();
    pre[src] = src;
    vis[src] = true;
    cap[src] = inf;
    dis[src] = 0;
    q.push(src);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int i=head[u]; ~i; i=node[i].next) {
            int v = node[i].v;
            if(node[i].w && dis[v] > dis[u]+node[i].val) {
                dis[v] = dis[u]+node[i].val;
                cap[v] = min(cap[u], node[i].w);
                pre[v] = i;
                if(!vis[v]) {
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    if(dis[des] == inf) return false;
    flow += cap[des];
    cost += cap[des] * dis[des];
    int u = des;
    while(u != src) {
        node[pre[u]].w -= cap[des];
        node[pre[u]^1].w += cap[des];
        u = node[pre[u]].u;
    }
    return true;
}

int MCMF(int src, int des) {
    int flow = 0, cost = 0;
    while(spfa(src, des, flow, cost));
    return cost;
}

vector<int> vv;
vector<pair <pair<int, int>, int> > vec;

int getid(int x) {
    return lower_bound(vv.begin(), vv.end(), x) - vv.begin() + 1;
}

void init() {
    tol = 0;
    vv.clear();
    vec.clear();
    mes(head, -1);
}

int main() {
    scanf("%d" ,&T);
    while(T--) {
        init();
        scanf("%d%d%d", &n, &k, &m);
        for(int i=1, u, v, w; i<=m; i++) {
            scanf("%d%d%d", &u, &v, &w);
            vec.push_back(make_pair(make_pair(u, v), w));
            vv.push_back(u);
            vv.push_back(v);
        }
        sort(vv.begin(), vv.end());
        vv.erase(unique(vv.begin(), vv.end()), vv.end());
        int src = 0, des = vv.size() + 2;
        for(int i=1; i<=vv.size(); i++) {
            addnode(i, i+1, inf, 0);
            addnode(i+1, i, 0, 0);
//          printf("%d %d %d %d\n", i, i+1, inf, 0);
        }
        addnode(src, 1, k, 0);
        addnode(1, src, 0, 0);
//      printf("%d %d %d %d\n", src, 1, k, 0);
        addnode(vv.size()+1, vv.size()+2, k, 0);
        addnode(vv.size()+2, vv.size()+1, 0, 0);
//      printf("%d %d %d %d\n", vv.size()+1, vv.size()+2, k, 0);
        for(auto i : vec) {
            int u = i.fi.fi, v = i.fi.se, w = i.se;
            u = getid(u);
            v = getid(v);
            addnode(u, v+1, 1, -w);
            addnode(v+1, u, 0, w);
//          printf("%d %d %d %d\n", u, v+1, 1, -w);
        }
        int ans = -MCMF(src, des);
        printf("%d\n", ans);
    }
    return 0;
}

转载于:https://www.cnblogs.com/Jiaaaaaaaqi/p/10904346.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值