hdu 4744 最小费用流

#include <cstdio>

#include <queue>

#include <cstring>

#include <cmath>

#define mul(a) (a)*(a)

using namespace std;



const int Maxn = 210;

const int Maxm = 100010;

const int inf = 0x3f3f3f3f;



struct ZKW_flow{

    int st, ed, ecnt, n;

    int head[Maxn];

    int cap[Maxm], cost[Maxm], to[Maxm], next[Maxm];



    void init(){

        memset(head, -1, sizeof(head));

        ecnt = 2;

    }



    void add(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 dis[Maxn];



    void SPFA(){

        for(int i = 0; i <= n; ++i) dis[i] = inf;

        priority_queue<pair<int, int> > Q;

        dis[st] = 0;

        Q.push(make_pair(0, st));

        while(!Q.empty()){

            int u = Q.top().second, d = -Q.top().first;

            Q.pop();

            if(dis[u] != d) continue;

            for(int p = head[u]; p!=-1; p = next[p]){

                int &v = to[p];

                if(cap[p] && dis[v] > d + cost[p]){

                    dis[v] = d + cost[p];

                    Q.push(make_pair(-dis[v], v));

                }

            }

        }

        for(int i = 0; i <= n; ++i) dis[i] = dis[ed] - dis[i];

    }



    int minCost, maxFlow;

    bool use[Maxn];



    int add_flow(int u, int flow){

        if(u == ed){

            maxFlow += flow;

            minCost += dis[st] * flow;

            return flow;

        }

        use[u] = true;

        int now = flow;

        for(int p = head[u]; p!=-1; p = next[p]){

            int &v = to[p];

            if(cap[p] && !use[v] && dis[u] == dis[v] + cost[p]){

                int tmp = add_flow(v, min(now, cap[p]));

                cap[p] -= tmp;

                cap[p^1] += tmp;

                now -= tmp;

                if(!now) break;

            }

        }

        return flow - now;

    }



    bool modify_label(){

        int d = inf;

        for(int u = 0; u <= n; ++u) if(use[u])

            for(int p = head[u]; p!=-1; p = next[p]){

                int &v = to[p];

                if(cap[p] && !use[v]) d = min(d, dis[v] + cost[p] - dis[u]);

            }

        if(d == inf) return false;

        for(int i = 0; i <= n; ++i) if(use[i]) dis[i] += d;

        return true;

    }



    int ZKW(int ss, int tt, int nn){

        st = ss, ed = tt, n = nn;

        minCost = maxFlow = 0;

        SPFA();

        while(true){

            while(true){

                for(int i = 0; i <= n; ++i) use[i] = 0;

                if(!add_flow(st, inf)) break;

            }

            if(!modify_label()) break;

        }

        return minCost;

    }

} G;

int w[Maxn];

struct Point{

    int x,y,z;

}p[Maxn];

int DIS(Point a,Point b)

{

    return (int)sqrt(1.0*mul(a.x-b.x)+1.0*mul(a.y-b.y)+1.0*mul(a.z-b.z));

}

int main()

{

    int n,i,j,sum;

    while(scanf("%d",&n),n){

        G.init();

        sum=0;

        for(i=1;i<=n;i++){

            scanf("%d%d%d%d",&p[i].x,&p[i].y,&p[i].z,&w[i]);

            sum+=w[i];

        }

        for(i=1;i<=n;i++){

            G.add(0,i,w[i],0);

            G.add(i+n,2*n+1,w[i],0);

            for(j=i+1;j<=n;j++){

                int cost=DIS(p[i],p[j]);

                G.add(i,j+n,inf,cost);

                G.add(j,i+n,inf,cost);

            }

        }

        int ans=G.ZKW(0,2*n+1,2*n+2);

        if(G.maxFlow==sum)

        printf("%d\n",ans);

        else

        printf("-1\n");

    }

    return 0;

}

 

你可能感兴趣的:(HDU)