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; }