现在的位置: 首页 > 综合 > 正文

ZOJ 3691 Flower

2013年07月03日 ⁄ 综合 ⁄ 共 2095字 ⁄ 字号 评论关闭

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4974

题意:给出空间中的一些点,在这些位置上各有 F[i] 朵花,最多可以从这个位置移出 L[i] 朵花(包括从其他地方移过来的),问最小移动半径 R 是多少时,能够把所有位置上的花移动到位置 1


二分半径(二分距离的平方,避免精度损失。结果一定是某两点之间的距离——很好理解哈)。

然后拆点,搞最大流就ok了……具体做法:从源点向n个点引出流量限制为花朵的个数F[i],拆开的点之间的流量限制为L[i],其他两点之间如果在半径R的条件下可以直接移动,流量限制为INF。汇点为题目中要求的第一个点。最终只需要判断流入汇点的流量是否等于从源点流出的总流量即可(即花朵总数)


顺便学习了一下algorithm里面的算法。太好用了吧……囧……

二分,去重什么的都不管了。

unique :返回去重后vector的尾端迭代器

sort :不多说了

e.erase(start_iterator, end_iterator) 删除vector中的元素

lower_bound(e.begin(), e.end(), val, can)    can是“比较函数”:两个参数can(r, tmp)一个是e中的元素,一个是传入的val值,比较两者关系的……不过这里val没有什么作用哈,随便就可以了。lower_bound返回满足条件的第一个值(最靠前的)的“位置”。



套了别人的网络流模板 ^_^

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 101
int g[N][N], n, x[N], y[N], z[N], f[N], l[N], all;
class Dinic{
public:
    static const int INF = 1000000007, SIZE = 205;
    int c[SIZE][SIZE];
    int n,s,t,l[SIZE],e[SIZE];
    int flow(int maxf = INF){
        int left=maxf;
        while(build()) left-=push(s,left);
        return maxf-left;
    }
    int push(int x, int f){
        if(x==t) return f;
        int& y=e[x],sum=f;
        for(;y<n;y++) if(c[x][y]>0 && l[x]+1==l[y]){
            int cnt=push(y,min(sum,c[x][y]));
            c[x][y]-=cnt;
            c[y][x]+=cnt;
            sum-=cnt;
            if(!sum) return f;
        }
        return f-sum;
    }
    bool build(){
        int m=0;
        memset(l,255,sizeof(l));
        l[e[m++]=s]=0;
        for(int i=0;i<m;i++) for(int y=0;y<n;y++)
            if(c[e[i]][y]>0 && l[y]<0) l[e[m++]=y]=l[e[i]]+1;
        memset(e,0,sizeof(e));
        return l[t]>=0;
    }
}net;
inline int dist(int i, int j) {
    return (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) + (z[i]-z[j])*(z[i]-z[j]);
}
bool can(int r, int tmp) {
    memset(net.c, 0, sizeof(net.c));
    for (int i=0; i<n; i++) {
        net.c[n+n][i] = f[i];
        net.c[i][i+n] = l[i];
        for (int j=0; j<n; j++)
            if (g[i][j] <= r) net.c[i+n][j] = Dinic::INF;
    }
    net.s = n+n;
    net.n = net.s + 1;
    net.t = 0;
    return net.flow() != all;
}
int main() {
    while (scanf("%d", &n) == 1) {
        all = 0;
        for (int i=0; i<n; i++) {
            scanf("%d%d%d%d%d", &x[i], &y[i], &z[i], &f[i], &l[i]);
            all += f[i];
        }
        vector<int> e;
        for (int i=0; i<n; i++) for (int j=i+1; j<n; j++) {
            g[i][j] = g[j][i] = dist(i, j);
            e.push_back(g[i][j]);
        }
        sort(e.begin(), e.end());
        e.erase(unique(e.begin(), e.end()), e.end());
        size_t t = lower_bound(e.begin(), e.end(), 0, can) - e.begin();
        if (t == e.size()) printf("-1\n");
        else printf("%.7lf\n", sqrt((double)e[t]));
    }
    return 0;
}

抱歉!评论已关闭.