POJ2391 Ombrophobic Bovines

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hanyuweining/article/details/84560198

传送门

发现惊天大错误QAQ

T上天然后发现自己的板子是假的QAQ

就是这一句

if(!cur)	return flow;

我之前一直写的是break。。。

注意实际意义

我们的dep[x]=-1是当前已经流不满无法増广了所以才把它设为-1不再增广

而流满了表示还可以继续增广所以直接return

我以前一直写的假板子直到这个题T飞。。。一个爆哭。。。

回归正传

这个题我们需要求最小化跑的最远的奶牛的时间

由此可以想到二分

二分以后我们需要找到最远的奶牛,可以通过预处理出两两牛棚的最短路来进行连边

所以最后的图大概是这个样子

对于每一个田地拆成两个点 初始牛和牛棚

源点连牛流量为牛的数量 牛棚连汇点流量为牛棚的容量 对于二分的mid 我们对dis[i][j]<=mid的连边流量为inf

然后看最后是否能满流就可以啦

二分+判断满流也是一个常见套路呢(另外一个是枚举+残存网络加边)

附代码。(注意longlong又一个爆哭)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define inf 1000000000000ll
#define ll long long
using namespace std;

struct edge{int to,lt;ll f;}e[320010],p[3010];
int in[420],cnt,s,t,n,m,ip[420];
queue<int> que;ll dis[420][420],dep[420],tot;
void addpath(int x,int y,ll f)
{
	p[++cnt].to=y;p[cnt].lt=ip[x];p[cnt].f=f;ip[x]=cnt;
	p[++cnt].to=x;p[cnt].lt=ip[y];p[cnt].f=f;ip[y]=cnt;
}
void add(int x,int y,ll f)
{
	e[++cnt].to=y;e[cnt].lt=in[x];e[cnt].f=f;in[x]=cnt;
	e[++cnt].to=x;e[cnt].lt=in[y];e[cnt].f=0;in[y]=cnt;
}
void floyd()
{
	memset(dis,48,sizeof(dis));//printf("%lld\n",dis[0][0]);
	for(int i=1;i<=n;i++)	dis[i][i]=0;
	for(int i=1;i<=n;i++)
		for(int j=ip[i];j;j=p[j].lt)
			dis[i][p[j].to]=min(dis[i][p[j].to],p[j].f);
	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 bfs()
{
	while(!que.empty())	que.pop();
	memset(dep,0,sizeof(dep));
	dep[s]=1;que.push(s);
	while(!que.empty())
	{
		int x=que.front();que.pop();
		//printf("%d %d\n",x,in[x]);printf("QAQ");
		for(int i=in[x];i;i=e[i].lt)
		{
			int y=e[i].to;
			if(!dep[y]&&e[i].f)
			{
				dep[y]=dep[x]+1;
				if(y==t)	return 1;
				que.push(y);
			}
		}
	}
	return 0;
}
ll dfs(int x,ll flow)
{
	if(x==t||!flow)	return flow;
	ll cur=flow;
	for(int i=in[x];i;i=e[i].lt)
	{
		int y=e[i].to;
		if(dep[y]==dep[x]+1&&e[i].f)
		{
			ll tmp=dfs(y,min(cur,e[i].f));
			e[i].f-=tmp;e[i^1].f+=tmp;cur-=tmp;
			if(!cur)	return flow;
		}
	}
	dep[x]=-1;
	return flow-cur;
}
ll dinic()
{
	ll ans=0;
	while(bfs())	ans+=dfs(s,inf);
	//printf("%d\n",ans);
	return ans;
}
int cow[400],she[400];
bool check(ll tmp)
{
	cnt=1;memset(in,0,sizeof(in));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j ++)
			if(dis[i][j]<=tmp)	add(i,n+j,inf);
	for(int i=1;i<=n;i++)	add(s,i,cow[i]),add(n+i,t,she[i]);
	ll cur=dinic();
	//printf("%lld %lld\n",tmp,cur);
	return cur==tot;
}
ll erf()
{
	ll l=0,r=inf,mid,ans=inf;
	while(l<=r)
	{
		mid=(l+r)>>1;//printf("%lld\n",mid);
		if(check(mid))	ans=mid,r=mid-1;
		else	l=mid+1;
	}
	return ans;
}
int main()
{
	//int n,m;
	scanf("%d%d",&n,&m);s=2*n+1;t=s+1;
	for(int i=1;i<=n;i++)	scanf("%d%d",&cow[i],&she[i]),tot+=cow[i];
	for(int i=1;i<=m;i++)
	{
		int x,y;ll f;
		scanf("%d%d%lld",&x,&y,&f);
		addpath(x,y,f);
	}
	floyd();ll ans=erf();
	printf("%lld\n",ans==inf?-1:ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/hanyuweining/article/details/84560198
POJ