ZOJ3691 Flower 最大流+拆点+二分

不喜欢读题的弱点暴露无遗,长时间接触简单的题目,能从数据一眼看出题目要求,问题比较严重。一开始看到3维坐标,再一看输出以为是道计算几何,所以直接没有去读题。。没想到是裸的最大流。。。。。这种毛病要改掉。 这次收到教训了

这是一道最大流满流判断的题目。

图中给我们N个点的坐标,算出两两的距离。

利用二分法 枚举最大值R。并用·最大流判断是否满流。

关于建图:

这里建图的基本思想就是拆点,把一个点i拆成i,i+n。 (我的建图中点1没有拆直接作为汇点,其他相同)详见build()函数

 

Flower

 


 

Time Limit: 8 Seconds                                     Memory Limit:65536 KB                                                     Special Judge                            

 


 

Gao and his girlfriend's relationship becomes better and better after they flying balloon last week. Thus,Gao wants to play a simple but evil game with his girlfriend at a late night. 

The game is simple: there is a three-dimensional space, Gao chooses N points to put flowers. For the point i, it has Fi flowers. And his girlfriend has to move all these flowers topoint 1 altogether. As everyone knows, his girlfriend is not strong likeGao, so she can move flowers from one point to another if and only if the Euclidean distance between two points are smaller or equal toR. In another words, she perhaps has to move flowers to the intermediate point for finally moving all flowers to the point one. In order to stay with his girlfriend as much time as possible, he asks his girlfriend, for the pointi, that she can only move out no more thanLi flowers (including the points as an intermediate point). 

Can you help his poor girlfriend to calculate the minimal R?

Input

There are multiple cases.

For each case, the first line contains an integer N (1 ≤ N ≤ 100), which means there areN points.

For the next N lines, each line contains five integers, Xi,Yi,Zi,Fi and Li. Xi, Yi and Zi are the coordinate of pointi (0 ≤ Xi, Yi, Zi ≤ 20000),Fi means there areFi flowers at the beginning.Li means this point can be moved out no more thanLi flowers.

Output

For each test case, it contains one real number indicating the minimal  R. The results should be rounded to seven decimal places. If there is no solution for this case, please output -1. Output's absolute error less than 1e-6 will be accepted.

Sample Input
2
1 1 1 1 1
2 2 2 2 2
Sample Output
1.7320508

 


                            Author: REN, Qing
                                                    Contest: ZOJ Monthly, March 2013

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>

using namespace std;

#define MAXN 300
#define INF 0x3FFFFFF
#define eps 1e-8

struct edge
{
	int to,c,next;
};

edge e[999999];
int que[MAXN*100];
int dis[MAXN],pre[MAXN];
int head[MAXN],head2[MAXN];
int st,ed,maxflow,en,n;
double x[MAXN],y[MAXN],z[MAXN];
int f[MAXN],l[MAXN],full;

void add(int a,int b,int c)
{
	e[en].to=b;
	e[en].c=c;
	e[en].next=head[a];
	head[a]=en++;
	e[en].to=a;
	e[en].c=0;
	e[en].next=head[b];
	head[b]=en++;
}

bool bfs()
{
	memset(dis,-1,sizeof(dis));
	que[0]=st,dis[st]=1;
	int t=1,f=0;
	while(f<t)
	{
		int j=que[f++];
		for(int k=head[j];k!=-1;k=e[k].next)
		{
			int i=e[k].to;
			if(dis[i]==-1 && e[k].c)
			{
				que[t++]=i;
				dis[i]=dis[j]+1;
				if(i==ed) return true;
			}
		}
	}
	return false;
}

int update()
{
	int p,flow=INF;
    for (int i=pre[ed];i!=-1;i=pre[i])
		if(e[head2[i]].c<flow) p=i,flow=e[head2[i]].c;
    for (int i=pre[ed];i!=-1;i=pre[i])
		e[head2[i]].c-=flow,e[head2[i]^1].c+=flow;
    maxflow+=flow;
    return p;
}

void dfs()
{
	memset(pre,-1,sizeof(pre));
	memcpy(head2,head,sizeof(head2));
    for(int i=st,j;i!=-1;)
    {
        int flag=false;
        for(int k=head[i];k!=-1;k=e[k].next)
          if(e[k].c && (dis[j=e[k].to]==dis[i]+1) )
          {
                pre[j]=i;
				head2[i]=k;
				i=j;
				flag=true;
                if(i==ed)
					i=update();
                if(flag)
					break;
          }
        if (!flag) dis[i]=-1,i=pre[i];
    }
}

int dinic()
{
	maxflow=0;
	while(bfs())
		dfs();
	return maxflow;
}

double getdis(int i,int j)
{
    return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]));
}

double maps[MAXN][MAXN];

void build(double len)
{
    en=0;
    memset(head,-1,sizeof(head));
    st=0,ed=1;
    add(st,ed,f[1]);
    for(int i=2;i<=n;i++)
    {
        add(st,i,f[i]);
        add(i,i+n,l[i]);
    }
    for(int i=2;i<=n;i++)
        for(int j=1;j<=n;j++)
        {

            if(i==j) continue;
            if(maps[i][j]==0) maps[i][j]=maps[j][i]=getdis(i,j);
            if(maps[i][j]<=len)
                add(i+n,j,INF);
        }
}

int main()
{
    while(~scanf("%d",&n))
    {
        full=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%d%d",&x[i],&y[i],&z[i],&f[i],&l[i]);
            full+=f[i];
        }
        double l=0,r=INF,m;
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                maps[i][j]=0;
        while(r-l>eps)
        {
            m=(l+r)/2;
            build(m);
            if(dinic()==full)
                r=m;
            else
                l=m;
        }
        if(r==INF)
            printf("-1\n");
        else
            printf("%.7lf\n",r);

    }

}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值