zoj3691 Flower

题意:在空间中给定n个点,给出每个点的三维坐标,以及每个点上已有的花的数目Fi,和可以从该点上移走的花的数目Li,因为每一次可以移动的距离有限,为R, 所以可以选择一个中介点进行转移,最后将所有的花都移动到第一个点上。
因为可以从每个点上移走的花的数目有限,所以,可以通过修改每次可以移动的距离R,  使得最终可以将所有的花移动到第一个点。 求最小的R。 若不存在,这输出-1
分析:求最小的R, 我们可以二分,转化为判定性问题。 如果已知R, 问是否能将所有的花移动到第一个点呢? 问题是否好解决一点了?? 将所有的花移动到第一个点,其实就是一个很明显的网络流判是否满流的问题了。
问题就是构图了。
虚拟一个源点,汇点就比较明显了,就是第一个点。
首先是拆点,将每一个点拆成一个 i点和 一个i +n, 连边,容量为Li,, 这是容量限制,表示经过该i点最多能有Li朵花(根据题目要求)
接着,根据R的距离,将可以转移的点连边, (注意是无向边,而且点已经拆成入点跟出点了,),容量为INF, 无穷大
再来是汇点,将所以与第一个点满足距离要求的点连边,容量也为INF
从源点往所有点连一条边,容量为Fi, 最后判断是否满流
zoj3691
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>

using namespace std;

const int N = 210;
const int M = 80010;
const double eps = 1e-7;
const int INF = 100000000;

int size,head[N],dis[N],gap[N],pre[N],cur[N];

struct edge
{
    int v,w,next;
    edge(){}
    edge(int v,int next,int w=0):v(v),next(next),w(w){}
}E[M];


inline void insert(int u,int v,int w)
{
    E[size]=edge(v,head[u],w);
    head[u]=size++;
    E[size]=edge(u,head[v],0);
    head[v]=size++;
}

int ISAP(int src,int des, int n)
{
    int maxflow=0;
    memset(dis,0,sizeof(dis));
    memset(gap,0,sizeof(gap));
    for(int i=0;i<=n;i++)
        cur[i]=head[i];
    int u=pre[src]=src;
    int aug=-1;
    while(dis[src]<n)
    {
loop:    for(int &i=cur[u];i!=-1;i=E[i].next)
        {
            int v=E[i].v;
            if(E[i].w && dis[u]==dis[v]+1)
            {
                aug=min(aug,E[i].w);
                pre[v]=u;
                u=v;
                if(v==des){
                    maxflow+=aug;
                    for(u=pre[u];v!=src;v=u,u=pre[u])
                    {
                        E[cur[u]].w-=aug;
                        E[cur[u]^1].w+=aug;
                    }
                    aug=INF;
                }
                goto loop;
            }
        }
        int mdis=n;
        for(int i=head[u];i!=-1;i=E[i].next)
        {
            int v=E[i].v;
            if(E[i].w && mdis>dis[v])
            {
                cur[u]=i;
                mdis=dis[v];
            }
        }
        if((--gap[dis[u]])==0)
            break;
        gap[dis[u]=mdis+1]++;
        u=pre[u];
    }
    return maxflow;
}

void init()
{
    memset(head,-1,sizeof(head));
    size=0;
}

int F[N], L[N], x[N], y[N], z[N];
double dist[N][N];

inline double getDist(int x1, int y1, int z1, int x2, int y2, int z2)
{
    return sqrt(double((x1 - x2) * 1ll * (x1 - x2) + (y1 - y2) * 1ll * (y1 - y2) + (z1 - z2) * 1ll * (z1 - z2)));
}

void init_Dist(int n)
{
    for(int i = 1; i <= n; ++i)
        for(int j = i + 1; j <= n; ++j)
        {
            dist[i][j] = getDist(x[i], y[i], z[i], x[j], y[j], z[j]);
            dist[j][i] = dist[i][j];
        }
}

void build(double mid, int n)
{
    for(int i = 2; i <= n; ++i)//拆点, 限容
        insert(i, i + n, L[i]);
    for(int i = 2; i <= n; ++i)//连边
        for(int j = i + 1; j <= n; ++j)
            if(dist[i][j] <= mid)
            {
                insert(i + n, j, INF);
                insert(j + n, i, INF);
            }
    for(int i = 2; i <= n; ++i)//汇点
    {
        if(dist[1][i] <= mid)
            insert(i + n, 1, INF);
    }
    for(int i = 2; i <= n; ++i)//源点
        insert(2 * n + 1, i, F[i]);
}
int main()
{
    int n;
    while(scanf("%d",&n) == 1)
    {
        bool flag = true;
        int tot = 0;
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d %d %d %d %d", &x[i], &y[i], &z[i], &F[i], &L[i]);
            tot += F[i];
        }
        tot -= F[1];

        init_Dist(n);
        double left = 0, right = 50000.0;
        double ans = -1;
        while(right - left > eps)//二分枚举答案
        {
            double mid = (left + right) / 2.0;
            init();
            build(mid, n);
            int tmp = ISAP(2 * n + 1, 1, 2 * n + 1);
            if(tmp == tot)
            {
                ans = mid;
                right = mid;
            }
            else left = mid;
        }
        if(ans < 0) puts("-1");
        else printf("%.7f\n",ans);

    }
    return 0;
}

 

posted @ 2013-04-03 13:18  枕边梦  阅读(293)  评论(0编辑  收藏  举报