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