2018 icpc焦作网络赛 F题 Modular Production Line (覆盖K区间的最小费用最大流)

本文探讨了一种优化策略,用于解决汽车工厂生产线在市场供过于求时如何通过生产副产品来最大化收益的问题。通过建立特定的数学模型,利用网络流算法中的最小费用最大流原理,文章提供了一个有效解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:https://nanti.jisuanke.com/t/31715

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

给出了1e5个点,但是因为最多200条边,也就是最多用到400个点,所用先离散化,然后建图。

u->v连边,费用为-w,流量为k。源点向1连一条流量为1,费用为0的边,最后一个点向汇点连流量为1,费用为0的点。

最关键的是i向i+1,连费用为0,流量为inf的边。因为点要受限于k。

AC代码:
 

#pragma GCC optimize(2)
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 100;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int  n, m, k, u, v, w, tot, T, N;
int head[maxn], dis[maxn], pre[maxn];
bool vis[maxn];
map<int, int>dp;
struct node
{
	int u, v, w;
}edg[maxn];
struct node1
{
	int v, cap, cost, next, flow;
}edge[maxn];
void init(int n)
{
	N = n;
	tot = 0;
	memset(head, -1, sizeof(head));
	return;
}
void addedge(int u, int v, int cap, int cost)
{
	edge[tot].v = v;
	edge[tot].cap = cap;
	edge[tot].cost = cost;
	edge[tot].flow = 0;
	edge[tot].next = head[u];
	head[u] = tot++;

	edge[tot].v = u;
	edge[tot].cap = 0;
	edge[tot].cost = -cost;
	edge[tot].flow = 0;
	edge[tot].next = head[v];
	head[v] = tot++;
	return;
}
bool spfa(int s,int t)
{
	for (int i = 0; i < N; i++)
	{
		pre[i] = -1;
		vis[i] = false;
		dis[i] = inf;
	}
	queue<int>q;
	dis[s] = 0;
	vis[s] = true;
	q.push(s);
	while (!q.empty())
	{
		int u = q.front();
		q.pop();
		vis[u] = false;
		for (int i = head[u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].v;
			if (edge[i].cap > edge[i].flow&&dis[v] > dis[u] + edge[i].cost)
			{
				dis[v] = dis[u] + edge[i].cost;
				pre[v] = i;
				if (!vis[v])
				{
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
	if (pre[t] == -1)
	{
		return false;
	}
	else
		return true;
}
int maxflow(int s, int t, int &cost)
{
	int flow = 0;
	cost = 0;
	while (spfa(s, t))
	{
		int _min = inf;
		for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].v])
		{
			_min = min(_min, edge[i].cap - edge[i].flow);
		}
		for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].v])
		{
			edge[i].flow += _min;
			edge[i ^ 1].flow -= _min;
			cost += edge[i].cost*_min;
		}
		flow += _min;
	}
	return flow;
}
int main()
{
	//freopen("C://input.txt", "r", stdin);
	scanf("%d", &T);
	map<int, int>::iterator it;
	while (T--)
	{
		scanf("%d%d%d", &n, &k, &m);
		dp.clear();
		for (int i = 1; i <= m; i++)
		{
			scanf("%d%d%d", &u, &v, &w);
			v++;
			edg[i].u = u;
			edg[i].v = v;
			edg[i].w = w;
			dp[u] = dp[v] = 1;
		}
		int cnt = 0;
		for (it = dp.begin(); it != dp.end(); it++)
		{
			int id = it->first;
			dp[id] = ++cnt;
		}
		init(cnt + 5);
		int s = 0;
		int t = cnt + 1;
		addedge(s, 1, k, 0);
		addedge(cnt, t, k, 0);
		for (int i = 1; i < cnt; i++)
		{
			addedge(i, i + 1, inf, 0);
		}
		for (int i = 1; i <= m; i++)
		{
			u = edg[i].u, v = edg[i].v;
			u = dp[u], v = dp[v];
			addedge(u, v, 1, -edg[i].w);
		}
		int cost;
		maxflow(s, t, cost);
		printf("%d\n", -cost);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值