【题意】:给出n头牛,b个农场,每个农场可以容纳一定数目的牛,每头牛对这B个农场都有一个确定的排名。为了使每头牛都尽量同等高兴,希望所有牛中最高兴的和最不高兴的程度差值最小,求这个差值。

【题解】:构图:源点s向每头牛连边,容量为1,表示每头牛只能选择一个农场;每个农场向汇点t连边,容量为农场可容纳牛的数目;二分枚举程度差值,如果牛i 对农场j 的排名在枚举的范围内,那么连边i->j,容量为1.对于每次二分枚举,判断构图后的最大流是否等于牛的数目即可。

【代码】:

  1 #include "iostream"
  2 #include "cstdio"
  3 #include "cstring"
  4 using namespace std;
  5 #define maxn 1100
  6 #define maxm 150000
  7 const int inf = 1 << 30;
  8 int n, m, s, t, b;
  9 int eh[maxn], low[maxn], pre[maxn], cur[maxn], tot, cnt[maxn], dist[maxn];
 10 int cow[1005][25], cap[25];
 11 struct Edge {
 12     int u, v, cap, flow, next;
 13 }et[maxm];
 14 
 15 void init() {
 16     tot = 0;
 17     memset(eh, -1sizeof(eh));
 18 }
 19 
 20 void add(int u, int v, int cap, int flow) {
 21     Edge e = {u, v, cap, flow, eh[u]};
 22     et[tot] = e;
 23     eh[u] = tot++;
 24 }
 25 
 26 void addedge(int u, int v, int cap) {
 27     add(u, v, cap, 0), add(v, u, 00);
 28 }
 29 
 30 int isap(int s, int t, int n) {
 31     int u, v, now, flow = 0;
 32     memset(dist, 0sizeof(dist));
 33     memset(cnt, 0sizeof(cnt));
 34     memset(low, 0sizeof(low));
 35     for(u = 0; u <= n; u++) cur[u] = eh[u];
 36     low[s] = inf, cnt[0= n;
 37     u = s;
 38     while(dist[s] < n) {
 39         for(now = cur[u]; now != -1; now = et[now].next) 
 40             if(et[now].cap - et[now].flow && dist[u] == dist[v = et[now].v] + 1)
 41                 break;
 42         if(now != -1) {
 43             cur[u] = pre[v] = now;
 44             low[v] = min(low[u], et[now].cap - et[now].flow);
 45             u = v;
 46             if(u == t) {
 47                 for(; u != s; u = et[pre[u]].u) {
 48                     et[pre[u]].flow += low[t];
 49                     et[pre[u]^1].flow -= low[t];
 50                 }
 51                 low[s] = inf, flow += low[t];
 52             }
 53         } else {
 54             if(--cnt[dist[u]] == 0break;
 55             dist[u] = n, cur[u] = eh[u];
 56             for(now = eh[u]; now != -1; now = et[now].next) 
 57                 if(et[now].cap - et[now].flow && dist[u] > dist[et[now].v] + 1)
 58                     dist[u] = dist[et[now].v] + 1;
 59             cnt[dist[u]]++;
 60             if(u != s) u = et[pre[u]].u;
 61         }
 62     }
 63     return flow;
 64 }
 65 
 66 bool build(int rank) {
 67     for(int st = 1; st <=  b - rank + 1; st++) {
 68         init();
 69         s = 0; t = n + b + 1;
 70         for(int i = 1; i <= n; i++) {
 71             addedge(s, i, 1);
 72             for(int j = st; j <= st + rank - 1; j++)
 73                 addedge(i, n + cow[i][j], 1);
 74         }
 75         for(int i = 1; i <= b; i++) addedge(n + i, t, cap[i]);
 76         if(isap(s, t, t - s + 1== n) return true;
 77     }
 78     return false;
 79 }
 80 
 81 int solve() {
 82     int l = 1, r = b, res = -1;
 83     while(l <= r) {
 84         int mid = (l + r) >> 1;
 85         if(build(mid)) res = mid, r = mid - 1;
 86         else l = mid + 1;
 87     }
 88     return res;
 89 }
 90 
 91 int main() {
 92     scanf("%d%d"&n, &b);
 93     for(int i = 1; i <= n; i++)
 94         for(int j = 1; j <= b; j++)
 95             scanf("%d"&cow[i][j]);
 96     for(int i = 1; i <= b; i++) scanf("%d"&cap[i]);
 97     int ans = solve();
 98     printf("%d\n", ans);
 99     return 0;
100 }
101