#HK5314. 「CEOI2025」BoardOina 游戏

「CEOI2025」BoardOina 游戏

注意事项

在 LibreOJ 上,由于语言限制,目前只支持以下语言的提交:

  • C++(标准为 C++ 17 及以上)

请在提交源代码前添加 #include "boardgames.h"。

题目描述

题目译自 CEOI 2025 Day1 T1「Boardgame Expo」

每年,克卢日-纳波卡都会举办一场大型桌游博览会,展示众多新游戏。今年的主要亮点是一款名为 BoardOina 的游戏。

有 nn 名玩家排成一队,等待尝试这款游戏。玩家按照队列顺序编号为 00 到 n−1n-1。玩家 00 在队列最前面,玩家 n−1n-1 在队列最后面。

队列中有 mm 个不同的友谊关系,涉及 mm 对玩家。具体来说,对于从 00 到 m−1m-1 的每个 ii,玩家 x[i]x[i] 和玩家 y[i]y[i] 是朋友,其中 0≤x[i]<y[i]<n0 \leq x[i] < y[i] < n。友谊关系是对称的。

考虑队列中从玩家 ss 开始的 kk 个连续玩家序列(对于任意 ss 和 kk,满足 0≤s<n0 \leq s < n 且 1≤k≤n−s1 \leq k \leq n-s)。如果对于该序列中的任意两个玩家,他们通过该朋友组内的友谊关系序列相连,则该玩家序列形成一个大小为 kk 的朋友组。具体来说,玩家 s,s+1,…,s+k−1s, s+1, \ldots, s+k-1 形成一个大小为 kk 的朋友组,如果对于每个 uu 和 vv(满足 s≤u<v<s+ks \leq u < v < s+k),存在一个玩家序列 p[0],…,p[l−1]p[0], \ldots, p[l-1],满足:

  • l≥2l \geq 2;
  • 对于每个 jj(从 00 到 l−1l-1),s≤p[j]<s+ks \leq p[j] < s+k;
  • p[0]=up[0] = u 且 p[l−1]=vp[l-1] = v;
  • 对于每个 jj(从 00 到 l−2l-2),玩家 p[j]p[j] 和 p[j+1]p[j+1] 是朋友。

注意,当 k=1k = 1 时,玩家 ss 单独形成一个大小为 11 的朋友组。

BoardOina 可以由任意数量的玩家游玩。然而,为了使游戏更成功,组织者只允许朋友组参与游戏。

一次只能有一个组玩游戏。对于每场游戏,从队列最前面的玩家开始形成一个朋友组,并开始玩游戏。该朋友组中的玩家从队列中移除。重复此过程,直到队列变空为止。形式上,我们说队列可以被分成 gg 个朋友组,如果存在一个组大小数组 K=[K[0],K[1],…,K[g−1]]K = [K[0], K[1], \ldots, K[g-1]],满足以下条件:

  • g>0g > 0 且对于每个 jj (0≤j<g)(0 \leq j < g),K[j]>0K[j] > 0;
  • K[0]+K[1]+…+K[g−1]=nK[0] + K[1] + \ldots + K[g-1] = n;
  • 对于每个 jj(从 00 到 g−1g-1),玩家 s[j],s[j]+1,…,s[j]+K[j]−1s[j], s[j]+1, \ldots, s[j]+K[j]-1 形成一个大小为 K[j]K[j] 的朋友组,其中 s[0]=0s[0]=0,否则 s[j]=K[0]+K[1]+…+K[j−1]s[j]=K[0]+K[1]+\ldots+K[j-1]。

组织者希望最小化玩游戏的朋友组数量。也就是说,他们希望将队列分成 gg 个朋友组,使得无法将队列分成 g−1g-1 个(或更少)朋友组。

你的任务是找到一个将队列分成最少朋友组的分组方式,并报告组大小数组。

实现细节

你应该实现以下程序:

std::vector<int> partition_players(int n, int m, std::vector<int> X, std::vector<int> Y)
  • nn:队列中的玩家数量。
  • mm:友谊关系的数量。
  • XX, YY:长度为 mm 的数组,描述友谊关系。
  • 该程序应返回一个组大小数组,表示将玩家队列分成最少数量的朋友组。
  • 对于每个测试点,该程序只被调用一次。

示例评测程序

示例评测程序读取以下格式的输入:

  • 第 11 行:n mn\ m
  • 第 2+i2 + i (0≤i<m)(0 \leq i < m) 行:x[i] y[i]x[i]\ y[i]

设 partition_players 返回的数组元素为 K[0],K[1],…,K[g−1]K[0], K[1], \ldots, K[g-1],其中 gg 为非负数。示例评测程序的输出格式如下:

  • 第 11 行:gg
  • 第 22 行:K[0] K[1] … K[g−1]K[0]\ K[1]\ \ldots\ K[g-1]

样例 1

考虑以下调用:

partition_players(5, 3, {0, 1, 3}, {1, 4, 4})

在这个示例中,玩家 00 和 11、玩家 11 和 44、以及玩家 33 和 44 是朋友。

玩家 22 在队列中没有朋友,因此必须单独形成一个大小为 11 的朋友组,这意味着最少朋友组数量为 g=3g = 3。另一方面,玩家 00 和 11,以及玩家 33 和 44 可以形成大小为 22 的朋友组。

因此,队列可以被分成 33 个朋友组,大小分别为 22、11 和 22,所以程序可以返回 [2, 1, 2]。

样例 2

考虑以下调用:

partition_players(7, 6, {0, 4, 2, 1, 2, 3}, {1, 5, 4, 5, 5, 6})

在这个示例中,玩家 00 和 11、玩家 44 和 55、玩家 22 和 44、玩家 11 和 55、玩家 22 和 55 以及玩家 33 和 66 是朋友。

玩家 33 的唯一朋友是玩家 66,因此任何包含玩家 33 的朋友组要么是:

  • 大小为 11 的朋友组,仅包含玩家 33;
  • 包含玩家 33 和玩家 66 的朋友组。

在第二种情况下,朋友组还必须包含玩家 44 和 55。这是不可能的,因为玩家 66 的唯一朋友是玩家 33,所以玩家 33 无法通过友谊关系序列与玩家 44 和 55 相连。

因此,玩家 33 必须被放入一个大小为 11 的朋友组。类似地,玩家 66 也必须被放入一个大小为 11 的朋友组,因此分组中的朋友组数量至少为 44。

玩家 00、11 和 22 无法形成一个大小为 33 的朋友组,因为玩家 00 或 11 无法通过组内的友谊关系序列与玩家 22 相连。如果组内有玩家 55,情况可能不同,但由于玩家 33 和 44 肯定会在不同的组中,这种情况不会发生。也就是说,分组中的朋友组数量至少为 55。

另一方面,玩家 00 和 11,以及玩家 44 和 55 可以形成两个大小为 22 的朋友组。

因此,队列可以被分成 55 个朋友组,大小分别为 22、11、11、22 和 11。程序可以返回 [2, 1, 1, 2, 1]。

数据范围与提示

对于所有输入数据,满足:

  • 2≤n≤100 0002 \leq n \leq 100\,000
  • 0≤m≤200 0000 \leq m \leq 200\,000
  • 对于每个 ii (0≤i<m)(0 \leq i < m),0≤x[i]<y[i]<n0 \leq x[i] < y[i] < n
  • 友谊关系是不同的。换句话说,对于每个 ii 和 jj (0≤i<j<m)(0 \leq i < j < m),x[i]≠x[j]x[i] \neq x[j] 或 y[i]≠y[j]y[i] \neq y[j]
  • 如果存在多个具有最小组数量的答案,你可以返回任意一个合法的答案。

详细子任务附加限制及分值如下表所示。

子任务 分值 附加限制
11 55 对于每个 ii(从 00 到 m−1m-1),y[i]=x[i]+1y[i] = x[i] + 1
22 77 对于每个 ii(从 00 到 m−1m-1),y[i]≤x[i]+2y[i] \leq x[i] + 2
33 66 n≤300n \leq 300 且 m≤600m \leq 600
44 1515 n≤2000n \leq 2000 且 m≤4000m \leq 4000
55 3434 没有循环的友谊关系。即,对于任意不同的玩家序列 p[0],p[1],…,p[l−1]p[0], p[1], \ldots, p[l-1] (l≥3)(l \geq 3),如果对于每个 0≤j<l−10 \leq j < l-1,玩家 p[j]p[j] 和 p[j+1]p[j+1] 是朋友,则玩家 p[0]p[0] 和 p[l−1]p[l-1] 不是朋友。
66 3333 无附加限制