题目链接:C.Jiaxun!
看到最小值最大很容易想到二分答案然后贪心 $\text{check}$ ,但是贪心可能相对来说容易写错,赛时讨论了好几种贪心策略,最后到一个半小时的时候才过了这题,至少还是一发过了没有因为额外罚时雪上加霜。
所以使用一个一定正确的 $\text{check}$ 尤为重要,故考虑网络流。
我们设二分出来的最小值为 $x$ 。 显然我们需要给三个人分配题数让他们的题数均大于 $x$ ,而每个人额外多分配的题数不用考虑,因为只有最小值才会影响答案,考虑每个人向汇点连接一条容量为 $x$ 的边,代表这个人至少需要 $x$ 道题,然后从源点向每一类题连边,容量为该类题目的数量,代表一共对于第 $i$ 类有 $cap_i$ 道题目可以提供,最后根据题目中对题目类型描述,对应题目类型向可以做这类题的人连边,容量为 $+\infty $ ,代表这个题目可以为对应的人提供做题数,然后跑最大流,判断 $maxflow$ 是否等于 $3*x$ ,如果等于则代表当前二分的 $x$ 可以被满足,否则无法满足。时间复杂度为 $O(T \log \frac{S}{3} V \sqrt E )$ ,在实现较好的情况下可以通过此题。
代码↓:
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define endl '\n'
const int MAXN = 1e2 + 10;
struct Edge
{
int to, next;
int val;
} edge[MAXN << 1];
int head[MAXN], tot = 1;
void addEdge(int u, int v, int val)
{
edge[++tot] = {v, head[u], val};
head[u] = tot;
edge[++tot] = {u, head[v], 0};
head[v] = tot;
}
int dep[MAXN], now[MAXN];
bool bfs(int s, int t)
{
for (int i = s; i <= t; i++)
dep[i] = 0;
queue<int> que;
dep[s] = 1;
now[s] = head[s];
que.push(s);
while (!que.empty())
{
int u = que.front();
que.pop();
for (int i = head[u]; i; i = edge[i].next)
{
int v = edge[i].to;
int w = edge[i].val;
if (!dep[v] && w)
{
dep[v] = dep[u] + 1;
now[v] = head[v];
que.push(v);
if (v == t)
return true;
}
}
}
return false;
}
int dfs(int u, int t, int sum)
{
if (u == t)
return sum;
int res = 0;
for (int &i = now[u]; i && sum; i = edge[i].next)
{
int v = edge[i].to;
int w = edge[i].val;
if (dep[v] == dep[u] + 1 && w)
{
int k = dfs(v, t, min(sum, w));
if (!k)
dep[v] = 0;
edge[i].val -= k;
edge[i ^ 1].val += k;
res += k;
sum -= k;
}
}
return res;
}
signed main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
int Case;
cin >> Case;
while (Case--)
{
int S;
cin >> S;
int n = 7;
vector<int> val(n + 1);
for (int i = 1; i <= n; i++)
cin >> val[i];
auto check = [&](int x) -> bool
{
const int INF = numeric_limits<int>::max();
int s = 0, t = n + 3 + 1;
for (int i = s; i <= t; i++)
head[i] = 0;
tot = 1;
for (int i = 1; i <= 3; i++)
addEdge(i + n, t, x);
for (int i = 1; i <= n; i++)
addEdge(s, i, val[i]);
addEdge(1, n + 1, INF);
addEdge(2, n + 2, INF);
addEdge(3, n + 1, INF);
addEdge(3, n + 2, INF);
addEdge(4, n + 3, INF);
addEdge(5, n + 1, INF);
addEdge(5, n + 3, INF);
addEdge(6, n + 2, INF);
addEdge(6, n + 3, INF);
addEdge(7, n + 1, INF);
addEdge(7, n + 2, INF);
addEdge(7, n + 3, INF);
int maxflow = 0;
while (bfs(s, t))
maxflow += dfs(s, t, INF);
return maxflow == 3 * x;
};
int l = 0, r = S / 3;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid))
l = mid;
else
r = mid - 1;
}
cout << l << endl;
}
return 0;
}
2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
新车首发,新的一年,只带想赚米的人coinsrore.com
新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
新车上路,只带前10个人coinsrore.com
新盘首开 新盘首开 征召客户!!!coinsrore.com
新项目准备上线,寻找志同道合的合作伙伴coinsrore.com
新车即将上线 真正的项目,期待你的参与coinsrore.com
新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com