计蒜客 Modular Production Line(ACM-ICPC 2018 焦作赛区网络预赛 F)(最长k可重区间集问题 费用流)

An automobile factory has a car production line. Now the market is oversupply and the production line is often shut down. To make full use of resources, the manager divides the entire production line into NN parts (1...N)(1...N). Some continuous parts can produce sub-products. And each of sub-products has their own value. The manager will use spare time to produce sub-products to make money. Because of the limited spare time, each part of the production line could only work at most KK times. And Because of the limited materials, each of the sub-products could be produced only once. The manager wants to know the maximum value could he make by produce sub-products.

Input

The first line of input is TT, the number of test case.

The first line of each test case contains three integers, N, KN,K and MM. (MM is the number of different sub-product).

The next MM lines each contain three integers A_i, B_i, W_iAi​,Bi​,Wi​ describing a sub-product. The sub-product has value W_iWi​. Only A_iAi​ to B_iBi​ parts work simultaneously will the sub-product be produced (include A_iAi​ to B_iBi​).

1 \le T \le 1001≤T≤100

1 \le K \le M \le 2001≤K≤M≤200

1 \le N \le 10^51≤N≤105

1 \le A_i \le B_i \le N1≤Ai​≤Bi​≤N

1 \le W_i \le 10^51≤Wi​≤105

Output

For each test case output the maximum value in a separate line.

样例输入复制

4
10 1 3
1 2 2
2 3 4
3 4 8
10 1 3
1 3 2
2 3 4
3 4 8
100000 1 3
1 100000 100000
1 2 3
100 200 300
100000 2 3
1 100000 100000
1 150 301
100 200 300

样例输出复制

10
8
100000
100301

题目来源

ACM-ICPC 2018 焦作赛区网络预赛

 

题意:生产产品有利润,但是需要时间,现在有K条生产线,问最大利润多少

 

解题思路:网络流24题原题 https://blog.csdn.net/icefox_zhx/article/details/78780575

建立源点S和汇点T,S向1点连接流量为k,边权为0的边,然后每个点向下一个点连接流量为无穷大,费用为0的边。对于每个线段,线段左端点向右端点连接流量为1,边权为线段长的边。最后的一个端点向T连接流量为k,费用为0的边,跑最大费用最大流即可。

要离散化。

#include <iostream>
#include <string.h>
#include <math.h>
#include <vector>
#include <algorithm>
#include <stdio.h>
#include <queue>
using namespace std;
const int MAXN = 40010;
const int INF = 0x3f3f3f3f;
typedef long long ll;

inline void scan_d(int &ret)
{
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9')
    {
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}
void Out(int a)
{   //  输出外挂
    if (a < 0)
    {
        putchar('-');
        a = -a;
    }
    if (a >= 10)
    {
       Out(a / 10);
    }
    putchar(a % 10 + '0');
}
struct edge
{
    int u, v, cap, cost, next;
} e[3 * MAXN];

int edge_num;
int head[500];

void insert_edge(int u, int v, int cap, int cost)
{
    e[edge_num].u = u;
    e[edge_num].v = v;
    e[edge_num].cap = cap;
    e[edge_num].cost = cost;
    e[edge_num].next = head[u];
    head[u] = edge_num++;

    //反向边 k^1即可求出反向边
    e[edge_num].u = v;
    e[edge_num].v = u;
    e[edge_num].cap = 0;      //注意这里
    e[edge_num].cost = -cost; //注意这里
    e[edge_num].next = head[v];
    head[v] = edge_num++;
}

int dis[500];
int pre[500];
bool vis[500];
bool spfa(int s, int t)
{
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    memset(pre, -1, sizeof(pre));

    dis[s] = 0;
    vis[s] = 1;
    queue<int> que;
    que.push(s);
    while (!que.empty())
    {
        int tp = que.front();
        que.pop();
        vis[tp] = 0;
        for (int i = head[tp]; ~i; i = e[i].next)
        {
            int v = e[i].v;
            int cost = e[i].cost;

            if (e[i].cap && dis[v] > dis[tp] + cost)
            {
                dis[v] = dis[tp] + cost;
                pre[v] = i;
                if (!vis[v])
                {
                    vis[v] = 1;
                    que.push(v);
                }
            }
        }
    }
    if (dis[t] == INF)
        return false;
    return true;
}

pair<int, int> MCMF(int s, int t)
{
    int maxflow = 0;
    int mincost = 0;
    int minc;
    while (spfa(s, t))
    {
        minc = INF;
        int cost = 0;
        for (int i = pre[t]; ~i; i = pre[e[i].u])
            minc = min(minc, e[i].cap);
        for (int i = pre[t]; ~i; i = pre[e[i].u])
        {
            e[i].cap -= minc;
            e[i ^ 1].cap += minc;
            cost += minc * e[i].cost; //flow*unit cost=total cost
        }
        mincost += cost;
        maxflow += minc;
    }
    return make_pair(mincost, maxflow);
}


int tot = 0;

int in[500];
int out[500];

int S, SK, T;

struct node{
    int b,e,w;
}p[500];


vector<int> num;

int main()
{
    int TT;
    scan_d(TT);
    while (TT--)
    {
        num.clear();
        edge_num = 0;
        memset(head, -1, sizeof(head));
        tot = 0;

        int N, M, K;
        scan_d(N);
        scan_d(K);
        scan_d(M);

        for (int i = 1; i <= M; i++){
            scan_d(p[i].b);
            scan_d(p[i].e);
            scan_d(p[i].w);
            p[i].e++;//左闭右开区间
            num.push_back(p[i].b);
            num.push_back(p[i].e);
        }
        sort(num.begin(),num.end());
        int cnt=unique(num.begin(),num.end())-num.begin();//离散化

        int S=++tot;
        int T=++tot;

        for(int i=0;i<cnt;i++){
            in[i]=++tot;
        }
        insert_edge(S,in[0],K,0);
        for(int i=0;i<cnt-1;i++)
            insert_edge(in[i],in[i+1],INF,0);
        for (int i = 1; i <= M; i++){
            p[i].b=lower_bound(num.begin(),num.begin()+cnt,p[i].b)-num.begin();
            p[i].e=lower_bound(num.begin(),num.begin()+cnt,p[i].e)-num.begin();
            insert_edge(in[p[i].b],in[p[i].e],1,-p[i].w);
        }
        insert_edge(in[cnt-1],T,K,0);
        Out(-MCMF(S, T).first);
        puts("");
    }

    return 0;
}



 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值