题意: 给出n个点。每个点有Fi朵花,和限制Li(总共能从i点移出Li朵花),同时给出点坐标(Xi,Yi,Zi)。问:能不能把所有点的花都移到第一个点?如果能,求出最小需求R(R是两点之间移动距离的限制,如果距离超出R,则此点的花就无法移动到那点)。
思路:很裸的网络流,拆点建图。i作为入点,i'作为出点,i和i'直接连一条容量为Li的边,距离为0。然后图中任意两点求出距离,连起来,容量为无穷。最后所有点连一个源点,容量为Fi,距离0,第一个点连一个汇点,容量为∑Fi。 建好图后二分答案即可。
代码:
#include<stdio.h> #include<algorithm> #include<iostream> #include<math.h> #include<set> #include<list> #include<map> #include<vector> #include<string.h> #include<queue> using namespace std; #define ll long long #define N 220 #define sq(x) ((x)*(x)) const int INF=0xfffffff; int n; struct node{ int x,y,z,f,l; }a[N]; int p[N],eid; struct edge{ int vid,next,vol,init; double cost; }e[(N*N)<<1]; void init() { eid=0; memset(p,-1,sizeof(p)); } void insert(int from,int to,int vol,double cost) { e[eid].vid=to; e[eid].init=vol; e[eid].cost=cost; e[eid].next=p[from]; p[from]=eid++; swap(from,to); e[eid].vid=to; e[eid].init=0; e[eid].cost=cost; e[eid].next=p[from]; p[from]=eid++; } int s,t; int gap[N],h[N]; int dfs(int u,int curFlow,int n,double maxd) { int v,resFlow=curFlow,minFlow,minh=n-1; if(u==t) return curFlow; for(int i=p[u];i!=-1;i=e[i].next){ v=e[i].vid; if(e[i].vol>0 && e[i].cost<=maxd){ if(h[u]==h[v]+1){ minFlow=min(resFlow,e[i].vol); minFlow=dfs(v,minFlow,n,maxd); e[i].vol-=minFlow; e[i^1].vol+=minFlow; resFlow-=minFlow; if(h[s]>=n) return curFlow-resFlow; if(resFlow==0) break; } if(h[v]<minh) minh=h[v]; } } if(resFlow==curFlow){ gap[h[u]]--; if(gap[h[u]]==0) h[s]=n; h[u]=minh+1; gap[h[u]]++; } return curFlow-resFlow; } bool ISAP(int n,int needFlow,double maxd) { int maxFlow=0; memset(gap,0,sizeof(gap)); memset(h,0,sizeof(h)); gap[0]=n; for(int i=0;i<eid;i++) e[i].vol=e[i].init; while(h[s]<n) maxFlow+=dfs(s,INF,n,maxd); return maxFlow==needFlow; } double solve(int needFlow) { double l=0,r=1e7,mid,e=1e-7; while(l+e<r){ mid=(l+r)/2; if(!ISAP(2*n+2,needFlow,mid)){ l=mid+1e-7; }else{ r=mid; } } if(r==1e7) return -1; else return r; } void makeMap(int sum) { double d; init(); s=0;t=n+n+1; for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ d=sqrt(0.0+sq(a[i].x-a[j].x)+sq(a[i].y-a[j].y)+sq(a[i].z-a[j].z)); insert(i+n,j,INF,d); insert(j+n,i,INF,d); } } for(int i=1;i<=n;i++){ insert(s,i,a[i].f,0); insert(i,i+n,a[i].l,0); } insert(1,t,sum,0); } int main() { int sum; while(scanf("%d",&n)!=EOF){ sum=0; for(int i=1;i<=n;i++){ scanf("%d%d%d%d%d",&a[i].x,&a[i].y,&a[i].z,&a[i].f,&a[i].l); sum+=a[i].f; } makeMap(sum); double ans=solve(sum); if(ans!=-1) printf("%.7f\n",ans); else puts("-1"); } return 0; }