[HDU 4009] Transfer water (最小树形图)

来源:互联网 发布:中年女士双肩背包 知乎 编辑:程序博客网 时间:2024/06/05 18:58

Transfer water

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4009

题目大意:

在一个小镇里面,有N户人家,每户人家的地址为(x,y,z)。现在要建立一个水循环系统,其中建立一个水井的费用与地址的高度成正比,即为X*z。而从一户有水井的人家接水到自己家的费用为:(|x2-x1| + |y2-y1| + |z2-z1|) * Y。当有水井的房子高度比其低时,需要加额外的Z元抽水费。
而且每户人家只允许自己的好友从自己家接水。现在问最小费用为多少

解题思路:

可以假想出一个房子0,并且只有0有水井。那么对于每户人家,如果要自己打水,那么相当于从0处接水。题目就变成了求有向图的最小树形图。

#include<iostream>#include<fstream>#include<cstdio>#include<cstring>#include<cmath>#include<map>#include<queue>#include<stack>#include<vector>#include<set>#include<ctype.h>#include<algorithm>#include<string>#define PI acos(-1.0)#define maxn 1100#define INF 1<<25#define mem(a, b) memset(a, b, sizeof(a))typedef long long ll;typedef int type;using namespace std;int n, X, Y, Z, m;struct point{    int x, y, z;}p[maxn];struct node{    int u, v;    type w;}e[maxn * maxn];type dis(point a, point b){    return abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z);}int pre[maxn], id[maxn], vis[maxn];type in[maxn];type Directed_MST(int root, int NV, int NE){    type ret = 0;    while(true)    {        for (int i = 0; i < NV; i++) in[i] = INF;        for (int i = 0; i < NE; i++)        {            int u = e[i].u, v = e[i].v;            if (e[i].w < in[v] && u != v)            {                pre[v] = u;                in[v] = e[i].w;            }        }        for (int i = 0; i < NV; i++)        {            if (i == root) continue;            if (in[i] == INF) return -1;        }        int cntcode = 0;        mem(id, -1), mem(vis, -1);        in[root] = 0;        for (int i = 0; i < NV; i++)        {            ret += in[i];            int v = i;            while(vis[v] != i && id[v] == -1 && v != root)            {                vis[v] = i;                v = pre[v];            }            if (v != root && id[v] == -1)            {                for (int u = pre[v]; u != v; u = pre[u])                    id[u] = cntcode;                id[v] = cntcode++;            }        }        if (!cntcode) break;        for (int i = 0; i < NV; i++) if (id[i] == -1)            id[i] = cntcode++;        for (int i = 0; i < NE; i++)        {            int v = e[i].v;            e[i].u = id[e[i].u];            e[i].v = id[e[i].v];            if (e[i].u != e[i].v) e[i].w -= in[v];        }        NV = cntcode;        root = id[root];    }    return ret;}int main (){    while(scanf("%d%d%d%d", &n, &X, &Y, &Z) != EOF)    {        if (n + X + Y + Z == 0) break;        m = 0;        for (int i = 1; i <= n; i++)        {            scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].z);            e[m].u = 0, e[m].v = i, e[m++].w = p[i].z * X;        }        for (int i = 1; i <= n; i++)        {            int k, d;            scanf("%d", &k);            while(k--)            {                scanf("%d", &d);                e[m].u = i, e[m].v = d, e[m].w = dis(p[i], p[d]) * Y;                if (p[i].z < p[d].z) e[m].w += Z;                m++;            }        }        type ans = Directed_MST(0, n + 1, m);        if (ans == -1) puts("poor XiaoA");        else printf("%d\n", ans);    }    return 0;}




0 0
原创粉丝点击