/******************************************************************************** 模板题。。。问题是比赛的时候一直没看出来,以为最小费用流,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; }