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

题目链接: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;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值