CF730I Olympiad in Programming and Sports 题解

容易发现可以直接转化成费用流模型。将学生分在一边,两个团队分在一边,就是一个二分图上的东西。由于 n3000n \leq 3000,右边只有 22 个点,所以直接费用流应该是可过的。但是我们考虑更优的做法。

既然可以转化成费用流,不妨考虑模拟费用流。我们考虑增广路的实际意义有可能是以下 44 种:

  • 一个目前没有加入团队的人加入了编程团队。

  • 一个目前没有加入团队的人加入了体育团队。

  • 一个目前在编程团队的人去了体育团队,另一个没加入团队的人去了编程团队。

  • 一个目前在体育团队的人去了编程团队,另一个没加入团队的人去了体育团队。

容易发现我们可以用堆维护之,本质上是个反悔贪心,复杂度 O(nlogn)O(n \log n)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
using namespace std;

const int N = 1e4 + 5;

int n, p, s, a[N], b[N];
int id[N];
struct Node
{
	int id, val;
	Node(int _u, int _v) : id(_u), val(_v) {}
	Node() {}
	bool operator<(const Node& g) const
	{
		return (val ^ g.val) ? (val < g.val) : (id < g.id);
	}
};

priority_queue<Node> pq1, pq2, pq3, pq4;

/*
pq1:能在A集合中的
pq2:能在B集合中的
pq3:能在A集合中的bi-ai
pq4:能在B集合中的ai-bi
*/

int main()
{
	scanf("%d%d%d", &n, &p, &s);
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &a[i]);
		pq1.push(Node(i, a[i]));
	}
	for (int i = 1; i <= n; i++)
	{
		scanf("%d", &b[i]);
		pq2.push(Node(i, b[i]));
	}
	int ans = 0;
	while (p > 0 || s > 0)
	{
		int maxp = -1, opt = 0;
		while (pq1.size() && id[pq1.top().id]) pq1.pop();
		while (pq2.size() && id[pq2.top().id]) pq2.pop();
		while (pq3.size() && id[pq3.top().id] != 1) pq3.pop();
		while (pq4.size() && id[pq4.top().id] != 2) pq4.pop();
		if (p && pq1.size() && pq1.top().val > maxp)
		{
			maxp = pq1.top().val;
			opt = 1;
		}
		if (s && pq2.size() && pq2.top().val > maxp)
		{
			maxp = pq2.top().val;
			opt = 2;
		}
		if (s && pq3.size() && pq1.size() && pq3.top().val + pq1.top().val > maxp)
		{
			maxp = pq3.top().val + pq1.top().val;
			opt = 3;
		}
		if (p && pq4.size() && pq2.size() && pq4.top().val + pq2.top().val > maxp)
		{
			maxp = pq4.top().val + pq2.top().val;
			opt = 4;
		}
		//printf("!: %d %d\n", maxp, opt);
		ans += maxp;
		if (opt == 1)
		{
			id[pq1.top().id] = 1;
			pq3.push(Node(pq1.top().id, b[pq1.top().id] - a[pq1.top().id]));
			p--;
		}
		else if (opt == 2)
		{
			int i = pq2.top().id;
			id[i] = 2;
			pq4.push(Node(i, a[i] - b[i]));
			s--;
		}
		else if (opt == 3)
		{
			s--;
			int i = pq3.top().id;
			id[i] = 2;
			pq4.push(Node(i, a[i] - b[i]));
			i = pq1.top().id;
			id[i] = 1;
			pq3.push(Node(i, b[i] - a[i]));
		}
		else
		{
			p--;
			int i = pq4.top().id;
			id[i] = 1;
			pq3.push(Node(i, b[i] - a[i]));
			i = pq2.top().id;
			id[i] = 2;
			pq4.push(Node(i, a[i] - b[i]));
		}
		//printf("!: %d %d\n", p, s);
	}
	printf("%d\n", ans);
	for (int i = 1; i <= n; i++) if (id[i] == 1) printf("%d ", i);
	printf("\n");
	for (int i = 1; i <= n; i++) if (id[i] == 2) printf("%d ", i);
	printf("\n");
	return 0;
}
posted @   HappyBobb  阅读(14)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示