HDU 4009 最小树形图

来源:互联网 发布:楼市2017迎巨变 知乎 编辑:程序博客网 时间:2024/06/05 21:49
/********************************************************************************    模板题。。。问题是比赛的时候一直没看出来,以为最小费用流,Racebug用邻接矩阵敲的,结果杯具TLE,要是用邻接表再稍微优化下的,就过了~********************************************************************************/#include <iostream>#include <algorithm>#include <cstdlib>#include <cstring>#include <utility>#include <cstdio>#include <memory>#include <string>#include <vector>#include <cmath>#include <ctime>#include <queue>#include <stack>#include <map>#include <set>using namespace std;typedef long long LL;typedef pair<int, int> PII;typedef pair<double, double> PDD;typedef map<int, int>::iterator MI;typedef vector<int>::iterator VI;typedef set<int>::iterator SI;const int INF_INT = 0x3f3f3f3f;const double oo = 10e9;const double eps = 10e-7;const double PI = acos(-1.0);const int MAXV = 1004;const int MAXE = MAXV * MAXV;struct Point{    int x, y, z;}pnt[MAXV];struct Edges{    int beg, end;    int cost;    int next;}edges[MAXE];int ecnt, head[MAXV];int n, X, Y, Z;int in[MAXV], pre[MAXV], id[MAXV], vis[MAXV];const int src = 0;inline int manhattan_dist(const Point &pa, const Point &pb){    return abs(pa.x - pb.x) + abs(pa.y - pb.y) + abs(pa.z - pb.z);}inline void add_edge(int u, int v, int c){    edges[ecnt].beg = u;    edges[ecnt].end = v;    edges[ecnt].cost = c;    edges[ecnt].next = head[u];    head[u] = ecnt++;    return ;}int directed_mst(int root, int vcnt){    int res = 0;    while (true)    {        fill(in, in + vcnt, INF_INT);        for (int i = 0; i < ecnt; ++i)        {            int u = edges[i].beg;            int v = edges[i].end;            if (edges[i].cost < in[v] && u != v)            {                pre[v] = u;                in[v] = edges[i].cost;            }        }        for (int i = 0; i < vcnt; ++i)        {            if (root == i)            {                continue ;            }            if (INF_INT == in[i])            {                return -1;            }        }        int ncnt = 0;        fill(id, id + vcnt, -1);        fill(vis, vis + vcnt, -1);        in[root] = 0;        for (int i = 0; i < vcnt; ++i)        {            res += in[i];            int v = i;            while (vis[v] != i && -1 == id[v] && v != root)            {                vis[v] = i;                v = pre[v];            }            if (v != root && -1 == id[v])            {                for (int u = pre[v]; u != v; u = pre[u])                {                    id[u] = ncnt;                }                id[v] = ncnt++;            }        }        if (0 == ncnt)        {            break ;        }        for (int i = 0; i < vcnt; ++i)        {            if (-1 == id[i])            {                id[i] = ncnt++;            }        }        for (int i = 0; i < ecnt; ++i)        {            int v = edges[i].end;            edges[i].beg = id[ edges[i].beg ];            edges[i].end = id[ edges[i].end ];            if (edges[i].beg != edges[i].end)            {                edges[i].cost -= in[v];            }        }        vcnt = ncnt;        root = id[root];    }    return res;}void ace(){    int k, u, v;    int ans, buf;    while (scanf("%d %d %d %d", &n, &X, &Y, &Z), n || X || Y || Z)    {        ++n;        ecnt = 0;        memset(head, -1, sizeof(head));        for (int i = 1; i < n; ++i)        {            scanf("%d %d %d", &pnt[i].x, &pnt[i].y, &pnt[i].z);        }        for (u = 1; u < n; ++u)        {            add_edge(src, u, pnt[u].z * X);        }        for (u = 1; u < n; ++u)        {            scanf("%d", &k);            while (k--)            {                scanf("%d", &v);                if (v == u)                {                    continue ;                }                buf = manhattan_dist(pnt[u], pnt[v]) * Y;                if (pnt[u].z < pnt[v].z)                {                    buf += Z;                }                add_edge(u, v, buf);             }        }        ans = directed_mst(src, n);        if (-1 == ans)        {            puts("poor XiaoA");        }        else        {            printf("%d\n", ans);        }    }    return ;}int main(){    ace();    return 0;}

原创粉丝点击