版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/85247909
打完才发现,这不就是我一直打的SPFA+多路增广+vis防走环吗。。。。。
AC Code:
#include<bits/stdc++.h>
#define maxn 305
#define maxm 200005
#define inf 0x3f3f3f3f
using namespace std;
int info[maxn],Prev[maxm],to[maxm],cap[maxm],cst[maxm],cnt_e;
inline void Node(int u,int v,int c,int ct){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cst[cnt_e]=ct,cap[cnt_e]=c; }
inline void Line(int u,int v,int c,int ct){ Node(u,v,c,ct),Node(v,u,0,-ct); }
int n,x[maxn],y[maxn],z[maxn],w[maxn];
int S,T,dis[maxn],acst,tot;
inline int sqr(int a){ return a*a; }
bool vis[maxn];
inline bool SPFA()
{
memset(dis,0x3f,sizeof dis);
static queue<int>q;
static int inq[maxn];
dis[T] = 0;q.push(T);
for(int now;!q.empty();)
{
now = q.front();q.pop();
for(int i=info[now];i;i=Prev[i])
if(cap[i^1] && dis[to[i]] > dis[now] + cst[i^1])
{
dis[to[i]] = dis[now] + cst[i^1];
if(!inq[to[i]]) inq[to[i]] = 1, q.push(to[i]);
}
inq[now] = 0;
}
return dis[S] < 0x3f3f3f3f;
}
int aug(int now,int Max)
{
if(now == T) return acst += Max * dis[S] , Max;
vis[now] = 1;
int st = Max , inc;
for(int i=info[now];i && st;i=Prev[i])
if(cap[i] && dis[now] - cst[i] == dis[to[i]] && !vis[to[i]])
{
inc = aug(to[i],min(cap[i],st));
st-=inc,cap[i]-=inc,cap[i^1]+=inc;
}
vis[now] = 0;
return Max - st;
}
int main()
{
for(;~scanf("%d",&n) && n;)
{
int stm = 0;acst=0;
tot = 2 * n;
S = ++tot , T = ++tot;
memset(info,0,sizeof info),cnt_e=1;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&x[i],&y[i],&z[i],&w[i]);
Line(S,i,w[i],0),Line(i+n,T,w[i],0);
stm+=w[i];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j)
{
int ds = floor(sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j])+sqr(z[i]-z[j])));
Line(i,j+n,inf,ds);
}
for(;SPFA();)
stm-=aug(S,inf);
if(stm) acst = -1;
printf("%d\n",acst);
}
}