传送门
其他不讲,就说说建图吧,下面以3个点为例:
我用的算法效率不高,想更快的可以用dinic或sap
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int n,en; int f[41111]; int fst[333],next[41111],node[41111],c[41111],lu[333],pre[333]; double l[41111]; double x[333],y[333],z[333]; int jj[333],cc[333]; bool vis[333]; int q[33333]; int af; void init() { af=0; en=0; memset(fst,-1,sizeof(fst)); } void add(int u,int v,double d,int cnt) { //cout<<u<<" "<<v<<" "<<d<<" "<<cnt<<endl; next[en]=fst[u]; fst[u]=en; node[en]=v; l[en]=d; c[en]=cnt; en++; } double dis(int i,int j) { return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j])); } void build() { for(int i=1; i<=n; i++) { add(0,i,0,jj[i]); add(i,0,0,0); } for(int i=2; i<=n; i++) { for(int j=2; j<=n; j++) { double d=dis(i,j); if(i==j) { add(i,n+j,d,cc[i]); add(n+j,i,d,0); } else { add(n+j,i,d,cc[j]); add(i,n+j,d,0); } } } for(int i=2; i<=n; i++) { double d=dis(1,i); add(n+i,1,d,cc[i]); add(1,n+i,d,0); } } bool bfs(int s,int t,double d) { memset(vis,0,sizeof(vis)); int fn=0,ed=0; q[ed++]=0; vis[0]=1; while(fn<ed) { int u=q[fn++]; for(int i=fst[u]; i!=-1; i=next[i]) { if(d-l[i]<1e-9)continue; int v=node[i]; if(c[i]-f[i]>0&&!vis[v]) { pre[v]=u; lu[v]=i; if(v==t)return true; q[ed++]=v; vis[v]=1; } } } return false; } int ek(int s,int t,double d) { int ans=0; memset(f,0,sizeof(f)); while(bfs(s,t,d)) { int mm=af; for(int i=t; i!=s; i=pre[i]) { int v=lu[i]; if(mm>c[v]-f[v])mm=c[v]-f[v]; } for(int i=t; i!=s; i=pre[i]) { int v=lu[i]; f[v]+=mm; f[v^1]-=mm; } ans+=mm; } return ans; } void solve() { double low=0,high=40000,mid; while(high-low>1e-9) { mid=(high+low)/2.0; if(ek(0,1,mid)==af)high=mid; else low=mid; } if(low>39999)cout<<-1<<endl; else printf("%.7f\n",low); } int main() { while(scanf("%d",&n)!=EOF) { init(); bool fff=0; for(int i=1; i<=n; i++) { scanf("%lf%lf%lf%d%d",&x[i],&y[i],&z[i],&jj[i],&cc[i]); af+=jj[i]; if(jj[i]>cc[i]&&i!=1)fff=1; } if(fff) { cout<<-1<<endl; continue; } build(); solve(); } return 0; }