# Description
Luogu传送门
# Solution
(感谢 @Acestar 提供的思路)
初始情况下,每头奶牛匹配一个礼物,所以我们把奶牛和礼物当作一个点。
如果奶牛 非常不要脸的去抢奶牛 的礼物( 向 连单向边),而且不幸的是奶牛 还打不过奶牛 ,那么 就被迫去抢别人的礼物 qwq,所以 就必须向它能抢到的别的奶牛连边。
因此我们这个图就建出来了,找一组解只需要跑一遍传递闭包即可,顺便拿个 优化一下,时间复杂度 ,跑的飞快。
# Code
@ShuKuang 已经成功卡到了目前最优解。
顺便感谢他提供的代码(
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using namespace std;
namespace IO {
template <typename T>
inline void read(T &x) {
x = 0; T r = 1;
char ch = getchar();
while (!isdigit(ch)) r = ch == '-' ? -1 : 1, ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
x *= r;
}
template <typename T, typename ...Args>
void read(T &x, Args &...args) {
read(x), read(args...);
}
template <typename T>
inline void write(T x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO;
bitset<511> f[511];
short n;
short a[511][511];
signed main() {
read(n);
for (short i = 1; i <= n; ++ i) {
for (short j = 1; j <= n; ++ j) {
read(a[i][j]);
}
}
for (short i = 1; i <= n; ++ i) {
for (short j = 1; j <= n; ++ j) {
if (a[i][j - 1] == i) break;
f[i][a[i][j]] = 1;
}
}
for (short j = 1; j <= n; ++ j) {
for (short i = 1; i <= n; ++ i) {
if (f[i][j])
f[i] |= f[j];
}
}
for (short i = 1; i <= n; ++ i) {
for (short j = 1; j <= n; ++ j) {
if (f[i][a[i][j]] && f[a[i][j]][i]) {
write(a[i][j]), putchar('\n');
break;
}
}
}
}