# Description
Luogu 传送门
# Solution
(感谢 @Acestar 提供的思路)
初始情况下,每头奶牛匹配一个礼物,所以我们把奶牛和礼物当作一个点。
如果奶牛 非常不要脸的去抢奶牛 的礼物( 向 连单向边),而且不幸的是奶牛 还打不过奶牛 ,那么 就被迫去抢别人的礼物 qwq,所以 就必须向它能抢到的别的奶牛连边。
因此我们这个图就建出来了,找一组解只需要跑一遍传递闭包即可,顺便拿个 优化一下,时间复杂度 ,跑的飞快。
# Code
@ShuKuang 已经成功卡到了目前最优解。
顺便感谢他提供的代码(
#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;  | |
            } | |
        } | |
    } | |
} |