1. 程式人生 > >HDU 4744 Starloop System(ZKW最小費用最大流)

HDU 4744 Starloop System(ZKW最小費用最大流)

打完才發現,這不就是我一直打的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);
	}
}