P6768 [USACO05MAR]Ombrophobic Bovines 发抖的牛
可以发现,牛如果想要去其他地点的雨棚,那么一定走最短路。
所以可以先
然后网络流判断可行性,即超级源点向每一块田地连一条容量为牛的个数的边,然后把田地和雨棚拆点,雨棚向超级汇点连容量为雨棚最多能放牛的个数的边。最后两点判断一次最短路,看是否可以加边。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstring>
#include <climits>
#include <queue>
using namespace std;
#define int long long
const int N = 5e6, INF = INT_MAX;
int dis[205][205], cow[N], rain[N], sum;
int n, p, T, S;
int e[N], h[N], c[N], ne[N], idx;
int cur[N], d[N];
void add(int x, int y, int z)
{
e[idx] = y, ne[idx] = h[x], c[idx] = z, h[x] = idx++;
e[idx] = x, ne[idx] = h[y], c[idx] = 0, h[y] = idx++;
}
void solve(int maxn)
{
for (int i = 0; i <= T; i++) h[i] = -1;
for (int i = 0; i <= idx; i++)
{
c[i] = ne[i] = e[i] = 0;
}
for (int i = 1; i <= n; i++)
{
add(S, i, cow[i]);
}
for (int i = 1; i <= n; i++)
{
add(i + n, T, rain[i]);
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (dis[i][j] <= maxn)
{
add(i, j + n, INF);
//add(j, i, INF);
//printf("%lld %lld\n", i, j);
}
}
}
}
bool bfs()
{
for (int i = 0; i <= T; i++) d[i] = -1;
queue<int> q;
q.push(S);
d[S] = 0;
cur[S] = h[S];
while (q.size())
{
int u = q.front();
q.pop();
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (d[j] == -1 && c[i] > 0)
{
d[j] = d[u] + 1;
cur[j] = h[j];
if (j == T) return 1;
q.push(j);
}
}
}
return 0;
}
int dfs(int u, int flow)
{
if (u == T) return flow;
int sum = 0;
for (int i = cur[u]; ~i && sum < flow; i = ne[i])
{
int j = e[i];
cur[u] = i;
if (d[j] == d[u] + 1 && c[i] > 0)
{
int f = dfs(j, min(c[i], flow - sum));
if (!f) d[j] = -1;
else
{
sum += f;
c[i] -= f;
c[i ^ 1] += f;
}
}
}
return sum;
}
int dinic()
{
int sum = 0, f;
while (bfs())
{
while (f = dfs(S, INF))
{
sum += f;
}
}
return sum;
}
bool check(int x)
{
solve(x);
return dinic() >= sum;
}
signed main()
{
memset(dis, 0x3f, sizeof dis);
scanf("%lld%lld", &n, &p);
T = 2 * n + 1;
for (int i = 1; i <= n; i++) scanf("%lld%lld", &cow[i], &rain[i]), dis[i][i] = 0, sum += cow[i];
for (int i = 1; i <= p; i++)
{
int u, v, w;
scanf("%lld%lld%lld", &u, &v, &w);
dis[u][v] = min(dis[u][v], w);
dis[v][u] = min(dis[v][u], w);
}
for (int k = 1; k <= n; k++)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
bool f = 0;
int l = 0, r = INF * 100;
while (l <= r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid - 1, f = 1;
else l = mid + 1;
}
printf("%lld\n", f ? r + 1 : -1);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现