luogu P2402 奶牛隐藏

本文解析洛谷P2402题目,介绍使用网络流算法解决奶牛迁徙问题的方法。通过构造特殊图模型,采用Floyd算法预处理最短路径,结合二分查找优化时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目传送门:https://www.luogu.org/problemnew/show/P2402



题意:

有n个点,m条边,每一个点一开始都有b1i头奶牛,并且都可以容纳b2i头奶牛,但是b1i有可能大于b2i,因此奶牛需要迁徙,迁徙的时间为路程的长度。求最小的时间,若无法完成,输出-1。



思路:

容易想到最短路floyd,因为可以与处理出从i点到j点的最短路(即时间花费)。

然后发现时间好像不能直接求,它具有单调性,再来个二分时间mid,若当前时间允许,则找更短的耗时,否则找更长的耗时。

最后发现可以用网络流求解,就是让不同的牛移动。

构图:

必然要拆点。

[1]源点向每一个点连一条流量为b1i的边,表示一开始这里有b1i头奶牛;

[2]每一个点向汇点连一条流量为b2i的边,表示最多能容纳b2i头奶牛;

[3]每一个点的入点向出点连一条流量为INF的边表示可以有无数头奶牛在这里中转;

[4]每一个点它能去到的点的最短路(即时间花费)小于等于二分的时间mid,则连一条流量为INF的边,表示从i点到j点在规定时间里可以有无数头奶牛走过。

有解的情况是flow=sum(b1的总和,即总的奶牛数),此时保证每一头奶牛都有一个被容纳的点,且每一个点都没有超过它的容量。



代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define INF 1e18
#define LL long long
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))
using namespace std; 
queue<int> f;
	struct node{int x,y,next;LL z;} a[100010];
	int b1[500],b2[500],last[1000];
	LL map[300][300];
	int n,m,len=-1,st,ed;
	LL s=0,ans=-1;
void ins(int x,int y,LL z)
{
	a[++len].x=x;a[len].y=y;a[len].z=z;a[len].next=last[x];last[x]=len;
}
int h[1000];
bool bfs()
{
	memset(h,0,sizeof(h));
	h[st]=1;
	f.push(st);
	while(!f.empty())
	{
		int x=f.front();
		for(int i=last[x];i>=0;i=a[i].next)
		{
			int y=a[i].y;
			if(a[i].z>0&&h[y]==0)
			{
				h[y]=h[x]+1;
				f.push(y);
			}
		}
		f.pop();
	}
	if(h[ed]) return true; else return false;
}
LL dfs(int x,LL f)
{
	LL s=0,t;
	if(x==ed) return f;
	for(int i=last[x];i>=0;i=a[i].next)
	{
		int y=a[i].y;
		if(a[i].z>0&&h[y]==h[x]+1&&f>s)
		{
			s+=(t=(dfs(y,min(f-s,a[i].z))));
			a[i].z-=t;
			a[i^1].z+=t;
		}
	}
	if(!s) h[x]=0;
	return s;
}
LL dinic()
{
	LL sum=0;
	while(bfs())
		sum+=dfs(st,INF);
	return sum;
}
LL work(LL x)
{
	len=-1;
	memset(last,-1,sizeof(last));	
	for(int i=1;i<=n;i++)
	{
		ins(st,i,b1[i]),ins(i,st,0);
		ins(i+n,ed,b2[i]),ins(ed,i+n,0);
		ins(i,i+n,INF),ins(i+n,i,0);
		for(int j=1;j<=n;j++)
			if(map[i][j]!=INF&&map[i][j]<=x) ins(i,j+n,INF),ins(j+n,i,0);
	}
	return dinic();
} 
int main()
{
	int x,y,z;
	LL l=1,r=0,mid;
	scanf("%d %d",&n,&m);
	st=n*2+1;
	ed=st+1;
	for(int i=1;i<=n;i++)
	{
		scanf("%d %d",&b1[i],&b2[i]);
		s+=b1[i];
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			map[i][j]=i==j?0:INF;
	for(int i=1;i<=m;i++)
	{
		scanf("%d %d %d",&x,&y,&z);
		if(map[x][y]>z) map[x][y]=map[y][x]=z;
		r=MAX(r,map[x][y]);
	}
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				map[i][j]=MIN(map[i][j],map[i][k]+map[k][j]),r=MAX(r,map[i][j]);
	while(l<=r)
	{
		mid=(l+r)>>1;
		if(work(mid)==s) r=mid-1,ans=mid; else l=mid+1;
	}
	printf("%lld",ans);
}

内容概要:本文介绍了多种开发者工具及其对开发效率的提升作用。首先,介绍了两款集成开发环境(IDE):IntelliJ IDEA 以其智能代码补全、强大的调试工具和项目管理功能适用于Java开发者;VS Code 则凭借轻量级和多种编程语言的插件支持成为前端开发者的常用工具。其次,提到了基于 GPT-4 的智能代码生成工具 Cursor,它通过对话式编程显著提高了开发效率。接着,阐述了版本控制系统 Git 的重要性,包括记录代码修改、分支管理和协作功能。然后,介绍了 Postman 作为 API 全生命周期管理工具,可创建、测试和文档化 API,缩短前后端联调时间。再者,提到 SonarQube 这款代码质量管理工具,能自动扫描代码并检测潜在的质量问题。还介绍了 Docker 容器化工具,通过定义应用的运行环境和依赖,确保环境一致性。最后,提及了线上诊断工具 Arthas 和性能调优工具 JProfiler,分别用于生产环境排障和性能优化。 适合人群:所有希望提高开发效率的程序员,尤其是有一定开发经验的软件工程师和技术团队。 使用场景及目标:①选择合适的 IDE 提升编码速度和代码质量;②利用 AI 编程助手加快开发进程;③通过 Git 实现高效的版本控制和团队协作;④使用 Postman 管理 API 的全生命周期;⑤借助 SonarQube 提高代码质量;⑥采用 Docker 实现环境一致性;⑦运用 Arthas 和 JProfiler 进行线上诊断和性能调优。 阅读建议:根据个人或团队的需求选择适合的工具,深入理解每种工具的功能特点,并在实际开发中不断实践和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值