Blog of RuSun

\begin {array}{c} \mathfrak {One Problem Is Difficult} \\\\ \mathfrak {Because You Don't Know} \\\\ \mathfrak {Why It Is Diffucult} \end {array}

P2857 [USACO06FEB]Steady Cow Assignment G

P2857 [USACO06FEB]Steady Cow Assignment G

最大值与最小值的跨度最小,考虑二分。首先二分确定跨度,在枚举最小值,即可确定每头牛可以选用的范围。

查看代码
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <iostream>
#include <cstdio>
#include <queue>
#include <climits>
#define INF INT_MAX
using namespace std;
const int N = 1030, M = 46050;
int n, B, st, ed, barn[N], d[N], cur[N], k[1010][30];
int idx = -1, hd[N], nxt[M], edg[M], wt[M];
bool bfs()
{
for (int i = st; i <= ed; i++)
d[i] = -1;
d[st] = 0;
cur[st] = hd[st];
queue <int> q;
q.push(st);
while (!q.empty())
{
int t = q.front();
q.pop();
for (int i = hd[t]; ~i; i = nxt[i])
if (d[edg[i]] == -1 && wt[i])
{
cur[edg[i]] = hd[edg[i]];
d[edg[i]] = d[t] + 1;
if (edg[i] == ed)
return true;
q.push(edg[i]);
}
}
return false;
}
int find(int x, int limit)
{
if (x == ed)
return limit;
int res = 0;
for (int i = cur[x]; ~i && res < limit; i = nxt[i])
{
cur[x] = i;
if (d[edg[i]] == d[x] + 1 && wt[i])
{
int t = find(edg[i], min(wt[i], limit - res));
if (!t)
d[edg[i]] = -1;
wt[i] -= t;
wt[i ^ 1] += t;
res += t;
}
}
return res;
}
int dinic()
{
int res = 0, flow;
while (bfs())
while (flow = find(st, INF))
res += flow;
return res;
}
bool check(int x)
{
for (int l = 1, r = l + x - 1; r <= B; l++, r++)
{
for (int i = 0; i <= idx; i += 2)
{
wt[i ^ 1] = 0;
if (edg[i ^ 1] == st)
{
wt[i] = 1;
continue;
}
else if (edg[i] == ed)
{
wt[i] = barn[edg[i ^ 1]];
continue;
}
int num = k[edg[i ^ 1]][edg[i] - n];
if (num < l || num > r)
wt[i] = 0;
else
wt[i] = 1;
}
if (dinic() == n)
return true;
}
return false;
}
void add(int x, int y, int z)
{
nxt[++idx] = hd[x];
hd[x] = idx;
edg[idx] = y;
wt[idx] = z;
}
int main()
{
cin >> n >> B;
st = 0;
ed = n + B + 1;
for (int i = st; i <= ed; i++)
hd[i] = -1;
for (int i = 1; i <= n; i++)
{
add(st, i, 1);
add(i, st, 0);
}
for (int i = 1, a; i <= n; i++)
for (int j = 1; j <= B; j++)
{
cin >> a;
k[i][a] = j;
add(i, a + n, 1);
add(a + n, i, 0);
}
for (int i = n + 1, a; i < ed; i++)
{
cin >> barn[i];
add(i, ed, barn[i]);
add(ed, i, 0);
}
int l = 1, r = B, mid;
while (l < r)
{
mid = l + r >> 1;
if (check(mid))
r = mid;
else
l = mid + 1;
}
cout << r;
return 0;
}