Transfer water

来源:互联网 发布:如何选购家具 知乎 编辑:程序博客网 时间:2024/06/05 01:54

题目

  http://acm.hdu.edu.cn/showproblem.php?pid=4009

题意

  给定n个点的三维坐标,以及根节点到每个点的单向权值,再给定n个节点间相互单向连接的成本,求最小树形图。

思路

  直接根据题意建图然后跑最小树形图模板,网上有人说这个题必定有解我觉得说法是错的,因为有些时候两点之间未必可以链接。

过程

  因为对模板不是很熟WA了很多发也DeBug了很久,发现是找完环之后忘了标记整个环,具体表现是80到83行之间的代码忘了写,所以一直在错。再就是发现定义虚根的先后次序不影响最后的结果,以及在网上寻找模板进行对比的时候发现了fill()这个函数。

fill(a,b,c);

等价于

for(int i=0 ; i<b ; i++) a[i] = c;

代码

////  main.cpp//  L////  Created by LucienShui on 2017/7/15.//  Copyright © 2017年 LucienShui. All rights reserved.//#include <iostream>#include <algorithm>#include <set>#include <string>#include <vector>#include <queue>#include <map>#include <stack>#include <iomanip>#include <cstdio>#include <cstring>#include <cmath>#include <cctype>#define il inline#define ll long long#define memset(a,b) memset(a,b,sizeof(a))using namespace std;#define maxn 1007struct {    int x, y, z;}point[maxn];struct {    int u, v;    ll w;}edge[maxn*maxn];ll in[maxn];int pre[maxn], id[maxn], vis[maxn];const int INF = 0x3f3f3f3f;int dis(int a, int b) {    int x = abs(point[a].x - point[b].x), y = abs(point[a].y - point[b].y),    z = abs(point[a].z - point[b].z);    return x + y + z;}ll directed_MST(int root, int n, int m) {    ll ans = 0;    while(true) {        fill(in, in+n, INF);//for(int i=0 ; i<n ; i++) in[i] = INF;        for(int i=0 ; i<m ; i++) {            int u = edge[i].u, v = edge[i].v;            if(edge[i].w < in[v] && u!=v) {                in[v] = edge[i].w;                pre[v] = u;            }        }        for(int i=0 ; i<n ; i++)            if(in[i] == INF && i != root)                return -1;        int cnt = 0;        memset(id, -1);        memset(vis, -1);        in[root] = 0;        for(int i=0 ; i<n ; i++) {            ans += 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] = cnt;                id[v] = cnt++;            }        }        if(cnt == 0) break;        /*line 80*/        for(int i=0 ; i<n ; i++)            if(id[i] == -1) id[i] = cnt++;        /*line 83*/        for(int i=0 ; i<m ; i++) {            int u = edge[i].u, v = edge[i].v;            edge[i].u = id[u];            edge[i].v = id[v];            if(id[u] != id[v]) {                edge[i].w -= in[v];            }        }        n = cnt;        root = id[root];    }    return ans;}int main (int argc, char* argv[]) {#ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);#endif    int n, m, tmp, v, X, Y, Z;    while(scanf("%d%d%d%d", &n, &X, &Y, &Z), (n || X || Y || Z)) {        m = 0;        for(int i=1 ; i<=n ; i++) {            scanf("%d%d%d", &point[i].x, &point[i].y, &point[i].z);            edge[m].u = 0;            edge[m].v = i;            edge[m++].w = X * point[i].z;        }        for(int u=1 ; u<=n ; u++) {            scanf("%d",&tmp);            while(tmp--) {                scanf("%d",&v);                if(u == v) continue;                edge[m].u = u;                edge[m].v = v;                edge[m].w = Y * dis(u,v);                if(point[u].z < point[v].z) {                    edge[m].w += Z;                }                m++;            }        }        ll ans = directed_MST(0,n+1,m);        if(ans == -1) puts("poor XiaoA");        else printf("%lld\n",ans);    }    return 0;}