思路:建图是显而易见的不过用普通的最小费用最大流超时了...改用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); } }
Description
Input
Output
Sample Input
3 0 0 2 1 0 2 0 1 2 0 0 1 3 0 0 2 2 0 2 0 1 2 0 0 1 3 0 0 2 3 0 2 0 1 2 0 0 1 0
Sample Output
6 8 -1