其他不讲,就说说建图吧,下面以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;
}