CF1139E Maximize Mex 题解
翻译中有一句话:校长将会从每个社团中各选出一个人。
就是一些人被分为一组,从每组中选一些人出来。
这就很容易想到通过二分图的匹配。
由于
我们从每个能力值
假如枚举的值为
但如果是这样的话,外层需要枚举到
考虑优化。
突然感觉与这道题很像,都是枚举值域,然后匹配。
于是就想到了一个玄学优化:用时间戳来优化常数。
在 CF 上交了一次,应该是数据太水,还过了。
代码:
const int N = 5e3, inf = 1e9 + 7;
int n, m, now, D, T;
int c[N + 5], p[N + 5], d[N + 5];
int mat[N + 5], vis[N + 5];
int cnt, head[N + 5];
struct Edge {
int v, ti, nxt;
} e[N + 5];
void add(int u, int v, int ti) {
e[++cnt].nxt = head[u];
e[cnt].v = v;
e[cnt].ti = ti;
head[u] = cnt;
}
bool dfs(int x) {
for (int i = head[x]; i; i = e[i].nxt)
if (e[i].ti > T && vis[e[i].v] != now) {
vis[e[i].v] = now;
if (mat[e[i].v] == -1 || dfs(mat[e[i].v])) { mat[e[i].v] = x; return 1; }
}
return 0;
}
int main() {
n = read(), m = read();
int W = 0;
for (int i = 1; i <= n; i++) p[i] = read(), W = max(W, p[i]);
for (int i = 1; i <= n; i++) c[i] = read();
D = read();
for (int i = 0; i <= n; i++) d[i] = inf; // 初始化到 n。
for (int i = 1; i <= D; i++) d[read()] = i;
for (int i = 1; i <= n; i++) add(p[i], c[i], d[i]);
for (int i = 1; i <= D; i++) {
T = i;
for (int j = 0; j <= m; j++) vis[j] = mat[j] = -1; // mat[j] 的值可能为 0 (p[i] == 0)
bool flag = 0;
for (int j = 0; j <= W; j++) {
now = j;
if (!dfs(j)) {
printf("%d\n", j);
flag = 1;
break;
}
}
if (!flag) printf("%d\n", W + 1);
}
return 0;
}
这样卡一下应该还是不能过,时间复杂度还是没有变。
发现答案肯定是单调不增的,于是倒序枚举,就用一个
时间复杂度
核心代码:
for (int i = D; i; i--) {
T = i;
for (int j = 0; j <= m; j++) vis[j] = 0;
while (dfs(tot)) { // 答案是具有单调性的。
tot++;
for (int j = 0; j <= m; j++) vis[j] = 0;
}
ans[i] = tot;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?