思路:建图是显而易见的不过用普通的最小费用最大流超时了...改用ZKW才过了
#include<bits/stdc++.h>
using namespace std;
const int maxn = 210;
const int maxm = 210*210*2;
#define INF 1e9
struct ZKW_flow{
int st,ed,ecnt,n;
int head[maxn];
int cap[maxm],cost[maxm],to[maxm],next[maxm];
void init()
{
memset(head,0,sizeof(head));
ecnt=2;
}
void addedge(int u,int v,int cc,int ww){
cap[ecnt]=cc;cost[ecnt]=ww;to[ecnt]=v;
next[ecnt]=head[u];head[u]=ecnt++;
cap[ecnt]=0;cost[ecnt]=-ww;to[ecnt]=u;
next[ecnt]=head[v];head[v]=ecnt++;
}
int d[maxn];
void spfa()
{
for(int i = 1;i<=n;i++)
d[i]=INF;
priority_queue<pair<int,int> >q;
d[st]=0;
q.push(make_pair(0,st));
while (!q.empty())
{
int u = q.top().second,di=-q.top().first;
q.pop();
if (d[u]!=di)continue;
for (int p = head[u];p;p=next[p])
{
int &v = to[p];
if (cap[p] && d[v]>di+cost[p])
{
d[v]=di+cost[p];
q.push(make_pair(-d[v],v));
}
}
}
for (int i = 1;i<=n;i++) d[i]=d[ed]-d[i];
}
int minCost,maxFlow;
bool use[maxn];
int add_flow(int u,int flow){
if (u==ed){
maxFlow+=flow;
minCost+=d[st]*flow;
return flow;
}
use[u]=1;
int now = flow;
for (int p = head[u];p;p=next[p]){
int &v = to[p];
if (cap[p] && !use[v] && d[u]==d[v]+cost[p]){
int temp = add_flow(v,min(now,cap[p]));
cap[p]-=temp;
cap[p^1]+=temp;
now-=temp;
if (!now)
break;
}
}
return flow-now;
}
bool modify_label()
{
int di = INF;
for (int u = 1;u<=n;u++)
if (use[u])
for (int p = head[u];p;p=next[p]){
int &v = to[p];
if (cap[p] && !use[v]) di = min(di,d[v]+cost[p]-d[u]);
}
if (di==INF)
return false;
for (int i = 1;i<=n;i++)
if (use[i])
d[i]+=di;
return true;
}
int min_cost_flow(int ss,int tt,int nn)
{
st=ss,ed=tt,n=nn;
minCost=maxFlow=0;
spfa();
while (1){
while (1){
for (int i = 1;i<=n;i++) use[i]=0;
if (!add_flow(st,INF)) break;
}
if (!modify_label()) break;
}
return minCost;
}
}zkw;
struct Point
{
int x,y,z,w;
}point[maxn];
int cal(int i,int j)
{
double xx = point[i].x-point[j].x;
double yy = point[i].y-point[j].y;
double zz = point[i].z-point[j].z;
return (int)sqrt(xx*xx+yy*yy+zz*zz);
}
int main()
{
int n;
while (scanf("%d",&n)!=EOF && n)
{
int sum = 0;
for (int i = 1;i<=n;i++)
{
scanf("%d%d%d%d",&point[i].x,&point[i].y,&point[i].z,&point[i].w);
sum+=point[i].w;
}
zkw.init();
int s = 2*n+1;
int t = s+1;
for (int i = 1;i<=n;i++)
{
zkw.addedge(s,i,point[i].w,0);
zkw.addedge(i+n,t,point[i].w,0);
for (int j = i+1;j<=n;j++)
{
int co = cal(i,j);
zkw.addedge(i,j+n,INF,co);
zkw.addedge(j,i+n,INF,co);
}
}
int ans = zkw.min_cost_flow(s,t,t);
if (zkw.maxFlow != sum)
ans=-1;
printf("%d\n",ans);
}
}