meaning of the title
Give a weighted digraph, select n + 1n+1 chains, and ask whether all points can be covered, if not, what is the minimum value of point weight that can not be covered
Sol
How to get rid of board problems in TJOI
After the binary answer, check the binary graph directly.
If you read more questions, you will find that what the questions require is the minimum path coverage that can be intersected. Then you can floyd once according to the routine, add edges in the bipartite graph if it can be connected, and then judge the maximum matching number. At first, I thought that because some points can not be selected, it is not necessary to be greedy for metaphysics when we are in Hungary, because we have asked for a pass through closure. So it's right to ask directly
Because \ (M \leqslant 500 \), Floyd needs to optimize with bitset
#include<bits/stdc++.h> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define se second //#define int long long #define ull signed long long #define LL long long #define Fin(x) {freopen(#x".in","r",stdin);} #define Fout(x) {freopen(#x".out","w",stdout);} using namespace std; const int MAXN = 1001, mod = 1e9 + 7, INF = 1e9 + 10; const double eps = 1e-9; template <typename A, typename B> inline bool chmin(A &a, B b){if(a > b) {a = b; return 1;} return 0;} template <typename A, typename B> inline bool chmax(A &a, B b){if(a < b) {a = b; return 1;} return 0;} template <typename A, typename B> inline LL add(A x, B y) {if(x + y < 0) return x + y + mod; return x + y >= mod ? x + y - mod : x + y;} template <typename A, typename B> inline void add2(A &x, B y) {if(x + y < 0) x = x + y + mod; else x = (x + y >= mod ? x + y - mod : x + y);} template <typename A, typename B> inline LL mul(A x, B y) {return 1ll * x * y % mod;} template <typename A, typename B> inline void mul2(A &x, B y) {x = (1ll * x * y % mod + mod) % mod;} template <typename A> inline void debug(A a){cout << a << '\n';} template <typename A> inline LL sqr(A x){return 1ll * x * x;} inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N, M, a[MAXN], ans[MAXN], vis[MAXN], tim = 1, link[MAXN], st[MAXN], top; bitset<MAXN> can[MAXN]; bool dfs(int x) { for(int i = 1; i <= top; i++) { if(can[st[x]][st[i]]) { if(vis[i] == tim) continue; vis[i] = tim; if(!link[i] || (dfs(link[i]))) {link[i] = x; return 1;} } } return 0; } bool check(int val) { memset(link, 0, sizeof(link)); top = 0; for(int i = 1; i <= M; i++) if(a[i] < val) st[++top] = i; int ans = 0; for(int i = 1; i <= top; i++, tim++) if(dfs(i)) ans++; return top - ans <= N + 1; } signed main() { N = read(); M = read(); int mx = 0; for(int i = 1; i <= M; i++) { a[i] = read(); int k = read(); mx = max(a[i], mx); for(int j = 1; j <= k; j++) can[i][read()] = 1; } for(int k = 1; k <= M; k++) for(int i = 1; i <= M; i++) if(can[i][k]) can[i] |= can[k]; int l = 0, r = mx, ans = 0; while(l <= r) { int mid = l + r >> 1; if(check(mid)) ans = mid, l = mid + 1; else r = mid - 1; } if(ans >= mx) puts("AK"); else cout << ans; return 0; } /* */