【USACO 2857】 Steady Cow Assignment
【题目链接】
【算法】
二分答案,check的时候跑最大流,即可
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 2000 #define MAXB 1000 int i,j,low,high,mid,st,ed,N,B,tot,ans,tmp; int h[MAXN+MAXB],U[MAXN*MAXB],V[MAXN*MAXB], W[MAXN*MAXB],Head[MAXN*MAXB],Next[MAXN*MAXB], other[MAXN*MAXB],v[MAXB+10],a[MAXN+10][MAXB+10]; template <typename T> void read(T &x) { int f=1; char c = getchar(); x=0; for (; !isdigit(c); c = getchar()) { if (c=='-') f = -f; } for (; isdigit(c); c = getchar()) x=x*10+c-'0'; x*=f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x/10); putchar(x % 10 + '0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } inline void add(int a,int b,int c) { ++tot; U[tot] = a; V[tot] = b; W[tot] = c; Next[tot] = Head[a]; Head[a] = tot; other[tot] = ++tot; U[tot] = b; V[tot] = a; W[tot] = 0; Next[tot] = Head[b]; Head[b] = tot; other[tot] = tot - 1; } inline bool bfs() { int i,x,y; queue<int> q; memset(h,0,sizeof(h)); h[st] = 1; q.push(st); while (!q.empty()) { x = q.front(); q.pop(); for (i = Head[x]; i; i = Next[i]) { y = V[i]; if ((W[i] > 0) && (!h[y])) { h[y] = h[x] + 1; q.push(y); } } } if (h[ed]) return true; else return false; } inline int maxflow(int x,int f) { int i,t,y,sum=0; if (x == ed) return f; for (i = Head[x]; i; i = Next[i]) { y = V[i]; if ((W[i] > 0) && (h[y] == h[x] + 1) && (sum < f)) { sum += (t = maxflow(y,min(W[i],f-sum))); W[i] -= t; W[other[i]] += t; } } if (!sum) h[x] = 0; return sum; } inline bool check(int ml) { int i,j,l,r,sum; for (l = 1; l <= N - ml + 1; l++) { r = l + ml - 1; for (i = 1; i <= tot; i++) Head[i] = 0; tot = 0; for (i = 1; i <= N; i++) add(st,i,1); for (i = 1; i <= B; i++) add(i+N,ed,v[i]); for (i = 1; i <= N; i++) { for (j = 1; j <= B; j++) { if ((a[i][j] >= l) && (a[i][j] <= r)) add(i,j+N,1); } } sum = 0; while (bfs()) { sum += maxflow(st,N); } if (sum == N) return true; } return false; } int main() { read(N); read(B); st = N + B + 1; ed = st + 1; for (i = 1; i <= N; i++) { for (j = 1; j <= B; j++) { read(tmp); a[i][tmp] = j; } } for (i = 1; i <= B; i++) read(v[i]); low = 0; high = B; while (low <= high) { mid = (low + high) / 2; if (check(mid)) { high = mid - 1; ans = mid; } else low = mid + 1; } writeln(ans); return 0; }