# Description

Luogu传送门

# Solution

(感谢 @Acestar 提供的思路)

初始情况下,每头奶牛匹配一个礼物,所以我们把奶牛和礼物当作一个点。

如果奶牛 ii 非常不要脸的去抢奶牛 jj 的礼物(iijj 连单向边),而且不幸的是奶牛 jj 还打不过奶牛 ii,那么 jj 就被迫去抢别人的礼物 qwq,所以 jj 就必须向它能抢到的别的奶牛连边。

因此我们这个图就建出来了,找一组解只需要跑一遍传递闭包即可,顺便拿个 bitset\text{bitset} 优化一下,时间复杂度 O(n3ω)O(\frac {n^3}\omega),跑的飞快。

# 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
#include <bits/stdc++.h>
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;
}
}
}

}