hdu 4009 Transfer water 最小树形图
2016-07-03 01:04
399 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4009
题目大意:
在山上有N户人家,每家的坐标为(xi, yi, zi)。每户人家要吃水,要么自己打井,花费为A zi,要么从别人的家引水渠代价为B
两家的曼哈顿距离,如果这家的海拔比供水的低,还要另外再买一个价值为C的水泵。问每家都有水吃的最低花费是多少。
每家都有水的目标一定能达成,大不了每家都打口井…
把所有能连水渠的两家连起来,就得到了一个有向图,答案一定一个森林。建立一个虚节点,向每个点连一条有向边,权值为在第i家挖井的代价,这样就把答案从森林变成了一棵树,求全图的一个最小树形图就是最低的代价。
学习了一下朱刘算法,算法思路还比较简单,实现起来很巧妙。算是一个模板吧。
#include<bits/stdc++.h>
#define N 1100
#define INF 0x3f3f3f3f
#define M 1100000
using namespace std;
int pre
,id
,visit
,in
;
struct node
{
int u,v,cost;
}edge[M];
int zhuliu(int root,int n,int m)
{
int res=0,u,v;
while(1)
{
for(int i=0;i<n;i++) in[i]=INF;
for(int i=0;i<m;i++)
if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v])
{
pre[edge[i].v]=edge[i].u;
in[edge[i].v]=edge[i].cost;
}
for(int i=0;i<n;i++)
if(i!=root&&in[i]==INF)
return -1;
int tn=0;
memset(id,-1,sizeof(id));
memset(visit,-1,sizeof(visit));
in[root]=0;
for(int i=0;i<n;i++)
{
res+=in[i];
v=i;
while(visit[v]!=i&&id[v]==-1&&v!=root)
{
visit[v]=i;
v=pre[v];
}
if(v!=root&&id[v]==-1)
{
for(int u=pre[v];u!=v;u=pre[u])
id[u]=tn;
id[v]=tn++;
}
}
if(tn==0) break;
for(int i=0;i<n;i++)
if(id[i]==-1)
id[i]=tn++;
for(int i=0;i<m;)
{
v=edge[i].v;
edge[i].u=id[edge[i].u];
edge[i].v=id[edge[i].v];
if(edge[i].u!=edge[i].v)
edge[i++].cost-=in[v];
else
swap(edge[i],edge[--m]);
}
n=tn;
root=id[root];
}
return res;
}
int n,x
,y
,z
,a,b,c,cnt;
void addedge(int u,int v,int cost)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt++].cost=cost;
}
int main()
{
while(~scanf("%d%d%d%d",&n,&a,&b,&c)&&n)
{
cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&x[i],&y[i],&z[i]);
addedge(0,i,a*z[i]);
}
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
for(int j=0;j<t;j++)
{
int u;
scanf("%d",&u);
if(u==i) continue ;
int cost=(abs(x[i]-x[u])+abs(y[i]-y[u])+abs(z[i]-z[u]))*b;
if(z[i]<z[u]) addedge(i,u,cost+c);
else addedge(i,u,cost);
}
}
cout<<zhuliu(0,n+1,cnt)<<endl;
}
}
题目大意:
在山上有N户人家,每家的坐标为(xi, yi, zi)。每户人家要吃水,要么自己打井,花费为A zi,要么从别人的家引水渠代价为B
两家的曼哈顿距离,如果这家的海拔比供水的低,还要另外再买一个价值为C的水泵。问每家都有水吃的最低花费是多少。
每家都有水的目标一定能达成,大不了每家都打口井…
把所有能连水渠的两家连起来,就得到了一个有向图,答案一定一个森林。建立一个虚节点,向每个点连一条有向边,权值为在第i家挖井的代价,这样就把答案从森林变成了一棵树,求全图的一个最小树形图就是最低的代价。
学习了一下朱刘算法,算法思路还比较简单,实现起来很巧妙。算是一个模板吧。
#include<bits/stdc++.h>
#define N 1100
#define INF 0x3f3f3f3f
#define M 1100000
using namespace std;
int pre
,id
,visit
,in
;
struct node
{
int u,v,cost;
}edge[M];
int zhuliu(int root,int n,int m)
{
int res=0,u,v;
while(1)
{
for(int i=0;i<n;i++) in[i]=INF;
for(int i=0;i<m;i++)
if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v])
{
pre[edge[i].v]=edge[i].u;
in[edge[i].v]=edge[i].cost;
}
for(int i=0;i<n;i++)
if(i!=root&&in[i]==INF)
return -1;
int tn=0;
memset(id,-1,sizeof(id));
memset(visit,-1,sizeof(visit));
in[root]=0;
for(int i=0;i<n;i++)
{
res+=in[i];
v=i;
while(visit[v]!=i&&id[v]==-1&&v!=root)
{
visit[v]=i;
v=pre[v];
}
if(v!=root&&id[v]==-1)
{
for(int u=pre[v];u!=v;u=pre[u])
id[u]=tn;
id[v]=tn++;
}
}
if(tn==0) break;
for(int i=0;i<n;i++)
if(id[i]==-1)
id[i]=tn++;
for(int i=0;i<m;)
{
v=edge[i].v;
edge[i].u=id[edge[i].u];
edge[i].v=id[edge[i].v];
if(edge[i].u!=edge[i].v)
edge[i++].cost-=in[v];
else
swap(edge[i],edge[--m]);
}
n=tn;
root=id[root];
}
return res;
}
int n,x
,y
,z
,a,b,c,cnt;
void addedge(int u,int v,int cost)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt++].cost=cost;
}
int main()
{
while(~scanf("%d%d%d%d",&n,&a,&b,&c)&&n)
{
cnt=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&x[i],&y[i],&z[i]);
addedge(0,i,a*z[i]);
}
for(int i=1;i<=n;i++)
{
int t;
scanf("%d",&t);
for(int j=0;j<t;j++)
{
int u;
scanf("%d",&u);
if(u==i) continue ;
int cost=(abs(x[i]-x[u])+abs(y[i]-y[u])+abs(z[i]-z[u]))*b;
if(z[i]<z[u]) addedge(i,u,cost+c);
else addedge(i,u,cost);
}
}
cout<<zhuliu(0,n+1,cnt)<<endl;
}
}
相关文章推荐
- Javascript.ReactNative-2-javascript-syntax-in-react-native
- javaScript基础学习(6)(瀑布流例子)
- 在C# 项目中添加NewtonSoft.json 的引用
- 阿里云服务器搭建ghost博客之Node环境安装(一)
- 数组去重,简短而有效的方法
- reactor设计模式
- 使用jQuery和Pure.CSS创建一个可编辑的表格
- js获取页面及个元素高度、宽度
- HTML初学体验
- CSS修改png图片的颜色
- Jquery 标签赋值问题
- 使用Slideout.js开发移动Web应用导航栏菜单
- 2015年双11手机淘宝前端技术之H5性能最佳实践
- JS如何判断滚动条是否滚到底部
- 7. Jsp 自定义标签
- Preference
- 提高node性能的奇怪办法
- 省市联动 js
- node.js后台jquery前台-- 实现用户登录注册AJAX交互
- JavaScript网页编程之------JavaScript与Html结合方式