HDU 4009 Transfer water【最小树形图】
2017-11-02 19:46
369 查看
题目链接
这里就有一个巧妙的办法,我们建立一个人工节点0,将节点0到其他节点的权值赋成在节点打井的费用即可。要注意的是如果是从低处向高处引水,除了引水费用还要加上水泵的钱。
这样建立新图后就相当于求最小树形图。
题目意思
小A住在一个村庄,去年洪水淹没了这个村庄。因此他们决定将整个村庄搬到附近的山上。山上没有泉水,因此每一家必须选择打一个井或者从别的人家引水。如果一家决定去挖一口井,则他们打井的费用是他们房子的高度,X每米。如果决定去引水,如果引水的地方比当前地方高,则引水的钱是这两家的距离成上Y美元每米。如果引水的地方比当前低。则必须需要水泵(除了引水线后)还要花费Z美元买一个水泵。除此之外,村民的关系是需要考虑的。一些村民不允许一些村民从他们的房子引水。现在给出3个实数(a,b,c)。每个房子的坐标。计算整个村庄都通上水的最小花费。如果不能,则输出不能。解题思路
这是一道最小树形图的题。因为每个点都可以选择打井或者是其他人家里引水,所以打井的位置是不能确定的。这里就有一个巧妙的办法,我们建立一个人工节点0,将节点0到其他节点的权值赋成在节点打井的费用即可。要注意的是如果是从低处向高处引水,除了引水费用还要加上水泵的钱。
这样建立新图后就相当于求最小树形图。
代码部分
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #define INF 0x3f3f3f3f using namespace std; int x,y,n,z; struct node { int x; int y; int z; } p[1002]; struct Edge { int u; int v; long long int w; } edge[1002*1002]; long long int dis(node a,node b) { long long int temp=abs(a.x-b.x)+abs(a.y-b.y)+abs(a.z-b.z); return temp; } ///closest[i]表示距离i最近的点,vis标记数组,in[i]存放节点的入边最小权值,id[i]存放节点的编号 int closest[1005],vis[1005],in[1005],id[1005]; int minroot; long long int min_cost(int root,int nodenum,int edgenum) { long long int ans=0; int i; while(true) { for(i=0; i<nodenum; i++) in[i]=INF; for(i=0; i<edgenum; i++) { int u=edge[i].u; int v=edge[i].v; ///u到v的权值如果比当前v的入边最小权还小,就更新最小权值,更新到v的最近的点为u if(u!=v&&edge[i].w<in[v]) { in[v]=edge[i].w; closest[v]=u; //if(u==root)///某个点的前驱节点是虚拟节点 // minroot=i; } } for(i=0; i<nodenum; i++) { if(i==root) continue; if(in[i]==INF) return -1; } int cnt=0; memset(vis,-1,sizeof(vis)); memset(id,-1,sizeof(id)); in[root]=0; for(i=0; i<nodenum; i++) { ans+=in[i]; int t=i; ///从t开始一直往前找,如果有环则会回到自身 while(vis[t]!=i&&id[t]==-1&&t!=root) { vis[t]=i; t=closest[t]; } if(t!=root&&id[t]==-1) { for(int u=closest[t]; u!=t; u=closest[u]) { id[u]=cnt; } id[t]=cnt++; } } if(cnt==0) break; for(i=0; i<nodenum; i++)///为不在环中的节点编号 { if(id[i]==-1) id[i]=cnt++; } for(i=0; i<edgenum; i++) { int s=edge[i].u; int t=edge[i].v; edge[i].u=id[s]; edge[i].v=id[t]; if(s!=t) edge[i].w=edge[i].w-in[t]; } nodenum=cnt; root=id[root]; } return ans; } int main() { int t,no; while(~scanf("%d%d%d%d",&n,&x,&y,&z)) { if(n==0&&x==0&&y==0&&z==0) break; for(int i=1; i<=n; i++) scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z); int k=0; for(int i=1; i<=n; i++) { edge[k].u=0; edge[k].v=i; edge[k].w=x*p[i].z; k++; } for(int i=1; i<=n; i++) { scanf("%d",&t); for(int j=1; j<=t; j++) { scanf("%d",&no); edge[k].u=i; edge[k].v=no; edge[k].w=dis(p[i],p[no])*y; if(p[i].z<p[no].z) { edge[k].w+=z; } k++; } } long long int ans=min_cost(0,n+1,k); if(ans<INF) printf("%lld\n",ans); else printf("poor XiaoA\n"); } return 0; }
相关文章推荐
- HDU 4009 Transfer water(最小树形图)
- HDU 4009 Transfer water(最小树形图)
- HDU 4009 Transfer water 最小树形图 朱刘算法
- HDU - 4009 Transfer water(最小树形图)
- Hdu 4009 Transfer water(最小树形图)
- HDU - 4009-Transfer water (最小树形图)
- HDU 4009 Transfer water 最小树形图
- Hdu 4009 Transfer water (最小树形图)
- hdu 4009 Transfer water(最小树形图生成森林)
- Transfer water - HDU 4009 - 最小树形图
- hdu 4009 Transfer water(最小树形图模板)
- HDU 4009 Transfer water 最小树形图
- hdu 4009 Transfer water 有固定根的最小树形图
- HDU 4009 Transfer water 最小树形图(简单题)
- HDU 4009 Transfer water(最小树形图)
- HDU 4009 Transfer water(最小树形图)
- HDU 4009 Transfer water 朱刘算法求无固定根最小树形图
- Hdu 4009 Transfer water【最小树形图】
- hdu 4009 Transfer water 最小树形图
- HDU 4009 Transfer water(最小树形图)