题解 CF1779E 【Anya's Simultaneous Exhibition】
StudyingFather · · 题解
给一个 官方题解 Bonus 部分中提到的“只进行
先考虑建立图论模型描述这个问题:对于
这个图显然有如下几个性质:
引理 1:如果一个人
引理 2:所有候选冠军构成一个强连通分量。
考虑对这个竞赛图的所有强连通分量缩点,有结论:
定理 1:对竞赛图缩点后,形成的图是一条链的传递闭包。即,链中的每个点向后面的每个点都连一条边,且
证明:
首先明确一点,竞赛图缩点后仍然是竞赛图,因此任意两个强连通分量之间必定存在一条边相连。
如果图上只有一个或两个强连通分量,则定理显然成立。
否则,图上至少有三个强连通分量。考虑图上任意的三个强连通分量
因此,缩点后链上的第一个点对应的强连通分量就是我们要求的候选冠军的集合。
有了前面这些结论,已经可以推出官方题解所给的
定理 2:在竞赛图中,将所有点按入度升序排序后,若前
证明:
考虑反证法。
-
-
\exists m > n$,前 $m$ 个点构成一个强连通分量。前 $n$ 个点之间的两两连边已经让这些点的入度和等于 $\dfrac{n(n - 1)}{2}$,因此并不存在前 $n$ 个点之外的其他点向前 $n$ 个点连边的情况,从而前 $m$ 个点并不是强连通的。$\square
(这个结论在 CF1498E 中也有用到)
因此我们得到如下算法:
- 对于点
i ,询问其与其他所有点的对战情况,得到i 的入度in_i ; - 将所有点按入度升序排序;
- 找到最小的
m 使得\sum_{i = 1}^m in_i = \dfrac{m(m-1)}{2} ,则前m 个点即为所求。
这样就只用
// Problem: E. Anya's Simultaneous Exhibition
// Contest: Codeforces - Hello 2023
// URL: https://codeforces.com/contest/1779/problem/E
// Author : StudyingFather
// Site : https://studyingfather.com
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <algorithm>
#include <iostream>
using namespace std;
int in[305], id[305], ans[305];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cout << '?' << ' ' << i << ' ';
for (int j = 1; j <= n; j++) cout << (i == j ? 0 : 1);
cout << endl;
cin >> in[i];
in[i] = n - 1 - in[i]; // in + out = n - 1
id[i] = i;
}
sort(id + 1, id + n + 1, [](int x, int y) { return in[x] < in[y]; });
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += in[id[i]];
if (sum == i * (i - 1) / 2) {
for (int j = 1; j <= i; j++) ans[id[j]] = 1;
break;
}
}
cout << "! ";
for (int i = 1; i <= n; i++) cout << ans[i];
cout << endl;
return 0;
}