每一户人家水的来源有两种打井和从别家接水,每户人家都可能向外输送水。

  打井和接水两种的付出代价都接边。设一个超级源点,每家每户打井的代价就是从该点(0)到该户人家(1~n)的边的权值。接水有两种可能,从高处接水,那么代价是哈密顿距离与Y的乘积(可以认为就是水管的费用);从低处接水,还要加上付出水泵的钱(水管+水泵的费用)。这样就可以建图了。图论,会建图的话问题就解决一半了。

  然后,用模版来解题。不过朱刘算法的模版时间复杂度的差异还是蛮大的。我的模版的建图是邻接矩阵,时间复杂度是O(N^3)。超时,过不了。在网上找了一份按前向星(边的起点、终点、权值)建图的模版。AC了。该算法的复杂度是O(M)。

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = , M=,INF=0x3f3f3f3f;
int pre[N],id[N],in[N],vis[N];
int tot;//边数
struct node
{
int u,v,w;
}e[M];
void adde(int i,int j,int k)
{
e[tot].u=i;e[tot].v=j;e[tot++].w=k;
}
int zhuliu(int root ,int vn)
{
int ans=;
int cnt;
while()
{
for(int i=;i<vn;i++)
in[i]=INF,id[i]=-,vis[i]=-;
for(int i=;i<tot;i++)
{
if(in[e[i].v]>e[i].w && e[i].u!=e[i].v)
{
pre[e[i].v]=e[i].u;
in[e[i].v]=e[i].w;
}
}
in[root]=;
pre[root]=root;
for(int i=;i<vn;i++)
{
ans+=in[i];
if(in[i]==INF)//这一步可以看出是否存在这样一棵树形图,因此可以略去DFS
return -;
}
cnt=;
for(int i=;i<vn;i++)
{
if(vis[i]==-)
{
int t=i;
while(vis[t]==-)
{
vis[t]=i;
t=pre[t];
}
if(vis[t]!=i || t==root) continue;
for(int j=pre[t];j!=t;j=pre[j])
id[j]=cnt;
id[t]=cnt++;
}
}
if(cnt==) break;
for(int i=;i<vn;i++)
if(id[i]==-)
id[i]=cnt++;
for(int i=;i<tot;i++)
{
int u,v;
u=e[i].u;
v=e[i].v;
e[i].u=id[u];
e[i].v=id[v];
e[i].w-=in[v];
}
vn=cnt;
root=id[root];
}
return ans;
} struct Node
{
int a,b,c;
}nd[N];
int main()
{
//freopen("test.txt","r",stdin);
int n,x,y,z,i,j,k,d;
while(scanf("%d%d%d%d",&n,&x,&y,&z)!=EOF)
{
if(!n) break;
tot=;
for(i=;i<=n;i++)
{
scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].c);
adde(,i,nd[i].c*x);
}
for(i=;i<=n;i++)
{
scanf("%d",&k);
while(k--)
{
scanf("%d",&j);
if(i==j) continue;
d=abs(nd[i].a-nd[j].a)+abs(nd[i].b-nd[j].b)+abs(nd[i].c-nd[j].c);
d*=y;
if(nd[i].c<nd[j].c) d+=z;
adde(i,j,d);
}
}
int ans=zhuliu(,n+);
if(ans==-) printf("poor XiaoA\n");
else printf("%d\n",ans);
}
return ;
}

下面是邻接矩阵建图的模版,虽然超时了。但是模版还是有借鉴意义的。模版来自哈工大出版的《图论及应用》。

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = , INF=0x3f3f3f3f;
int Map[N][N];
bool vis[N],f[N];
//f是缩点标记,1表示该点已经被缩掉
int pre[N];
int zhuliu(int n)
{
int sum=;
int i,j,k;
for(i=;i<n;i++)
{
f[i]=;
Map[i][i]=INF;
}
pre[]=;
while()
{
//求最短弧集合E0
for(i=;i<n;i++)
{
if(f[i]) continue;
pre[i]=i;
for(j=;j<n;j++)
if(!f[j]&&Map[j][i]<Map[pre[i]][i]) pre[i]=j;
if(pre[i]==i) return -; //没有入边,不存在最小树形图
}
//检查E0
for(i=;i<n;i++)
{
if(f[i]) continue ;
//从当前点开始找环
for(j=;j<n;j++) vis[j]=;
vis[]=;
j=i;
do
{
vis[j]=;
j=pre[j];
}
while(!vis[j]) ;
if(!j) continue; //没有找到环
//收缩G中的有向环
i=j;
//将整个环的权值保存,累计入原图的最小树形图
do
{
sum+=Map[pre[j]][j];
j=pre[j];
}
while(j!=i) ;
j=i;
//对与环上的点有关的边,修改边权
do
{
for(k=; k<n; k++)
if(!f[k]&&Map[k][j]<INF&&k!=pre[j])
Map[k][j]-= Map[pre[j]][j];
j=pre[j];
}
while(j!=i) ;
//缩点,将整个环缩成i号点,所有与环上的点有关的边转移到点i
for(j=;j<n;j++)
{
if(j==i) continue;
for(k=pre[i]; k!=i; k=pre[k])
{
if(Map[k][j]<Map[i][j]) Map[i][j] =Map[k][j];
if(Map[j][k]<Map[j][i]) Map[j][i] =Map[j][k];
}
}
//标记环上其他的点为被缩掉
for(j=pre[i];j!=i;j=pre[j]) f[j] =;
//当前环缩点结束,形成新的图G’,跳出继续求G’的最小树形图
break;
}
//如果所有的点都被检查且没有环存在,现在的最短弧集合E0就是
//最小树形图,累计如sum, 算法结束
if(i==n)
{
for(i=;i<n;i++) if(!f[i]) sum+=Map[pre[i]][i];
break;
}
}
return sum;
} struct node
{
int a,b,c;
}nd[N];
int main()
{
//freopen("test.txt","r",stdin);
int n,x,y,z,i,j,k,d;
while(scanf("%d%d%d%d",&n,&x,&y,&z)!=EOF)
{
if(!n) break;
for(i=;i<=n;i++)
for(j=;j<i;j++)
Map[j][i]=Map[i][j]=INF;
for(i=;i<=n;i++)
{
scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].c);
Map[][i]=nd[i].c*x;
}
for(i=;i<=n;i++)
{
scanf("%d",&k);
while(k--)
{
scanf("%d",&j);
if(i==j) continue;
d=abs(nd[i].a-nd[j].a)+abs(nd[i].b-nd[j].b)+abs(nd[i].c-nd[j].c);
d*=y;
if(nd[i].c>=nd[j].c) d+=z;
Map[i][j]=min(d,Map[i][j]);
}
}
printf("%d\n",zhuliu(n+));
}
return ;
}

hdu4009 Transfer water 最小树形图的更多相关文章

  1. HDU4009 Transfer water —— 最小树形图 + 不定根 + 超级点

    题目链接:https://vjudge.net/problem/HDU-4009 Transfer water Time Limit: 5000/3000 MS (Java/Others)    Me ...

  2. HDU 4009 Transfer water 最小树形图

    分析:建一个远点,往每个点连建井的价值(单向边),其它输水线按照题意建单向边 然后以源点为根的权值最小的有向树就是答案,套最小树形图模板 #include <iostream> #incl ...

  3. HDOJ 4009 Transfer water 最小树形图

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) T ...

  4. HDU4009 Transfer water 【最小树形图】

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) T ...

  5. POJ 3164 Command Network 最小树形图模板

    最小树形图求的是有向图的最小生成树,跟无向图求最小生成树有很大的区别. 步骤大致如下: 1.求除了根节点以外每个节点的最小入边,记录前驱 2.判断除了根节点,是否每个节点都有入边,如果存在没有入边的点 ...

  6. HDU 4009——Transfer water——————【最小树形图、不定根】

    Transfer water Time Limit:3000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64u Subm ...

  7. HDU 4009 Transfer water(最小树形图)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4009 题意:给出一个村庄(x,y,z).每个村庄可以挖井或者修建水渠从其他村庄得到水.挖井有一个代价, ...

  8. 最小树形图(hdu4009)

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) T ...

  9. HDU4009:Transfer water(有向图的最小生成树)

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)To ...

随机推荐

  1. localStorage、sessionStorage、cookie

    vue下的全局变量和vuex里的state都是临时变量,页面刷新就都没了.

  2. 基于MATLAB的多功能语音处理器

    一.设计功能 录制音频,保存音频 对录制的语音信号进行频谱分析,确定该段语音的主要频率范围: 利用采样定理,对该段语音信号进行采样,观察不用采样频率(过采样.欠采样.临界采样)对信号的影响: 实现语音 ...

  3. loadrunner录制不了

    我在使用loadrunner过程中遇到的问题是,录制脚本时候能够打开firefox,但是无法打开IE,降低IE版本以后仍然不行. 1.在录制脚本时Start Recoding中,默认如下,这样有可能I ...

  4. 原来这才是Kafka的“真面目”

    作者介绍 郑杰文,腾讯云存储,高级后台工程师,2014 年毕业加入腾讯,先后从事增值业务开发.腾讯云存储开发.对业务性.技术平台型后台架构设计都有深入的探索实践.对架构的海量并发.高可用.可扩展性都有 ...

  5. 为 Elasticsearch 添加中文分词,对比分词器效果

    转自:http://keenwon.com/1404.html 为 Elasticsearch 添加中文分词,对比分词器效果 Posted in 后端 By KeenWon On 2014年12月12 ...

  6. 【codeforces 350C】Bombs

    [链接] 我是链接,点我呀:) [题意] [题解] 会发现在x轴以及y轴上的炸弹,能用较少的操作数除掉. 而其他的点,会发现操作数都是一样的. 那么先把x,y轴上的点都除掉. 其他点. 我们优先沿着横 ...

  7. ZOJ - 3483 - Gaussian Prime

    先上题目: Gaussian Prime Time Limit: 3 Seconds      Memory Limit: 65536 KB In number theory, a Gaussian ...

  8. mysql use index () 优化查询的例子

    USE INDEX在你查询语句中表名的后面,添加 USE INDEX 来提供你希望 MySQ 去参考的索引列表,就可以让 MySQL 不再考虑其他可用的索引.Eg:SELECT * FROM myta ...

  9. HTML【2】表单提交与服务层的模拟(具体解释get与post提交方式的不同)

    在HTML[1]中已经说明了HTML编程的基本方式,最后说到了表单提交的方式有get和post方式.那么究竟什么是get/post 方式呢,两者有什么差别?如今我就详细的介绍一下. 首先回想一下表单的 ...

  10. hdu5326 Work

    题目链接:点击打开链接 题目大意:有n个人.各自管理不同的人,问有多少人管理k个人. 思路:先记录每一个人的直接上级.然后模拟路径压缩的过程进行计数求和. #include<stdio.h> ...