zoukankan      html  css  js  c++  java
  • POJ2391 Ombrophobic Bovines

    传送门

    发现惊天大错误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
    ",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
    ",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
    ",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
    ",tmp,cur);
    	return cur==tot;
    }
    ll erf()
    {
    	ll l=0,r=inf,mid,ans=inf;
    	while(l<=r)
    	{
    		mid=(l+r)>>1;//printf("%lld
    ",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
    ",ans==inf?-1:ans);
    	return 0;
    }
    
  • 相关阅读:
    50道sql练习题和答案
    异步编程的数据同步
    浅说异步编程
    进程、应用程序域,线程和上下文之间的关系
    关于薪资和技术的一些思考
    SharePoint2013 列表栏设置
    SharePoint2013 功能区的配置
    EF Code First 数据迁移配置
    EF CodeFirst 数据库初始化策略
    用加减边距写图片轮播
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10321952.html
Copyright © 2011-2022 走看看