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

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

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

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. using namespace std;
  5. const int N = , M=,INF=0x3f3f3f3f;
  6. int pre[N],id[N],in[N],vis[N];
  7. int tot;//边数
  8. struct node
  9. {
  10. int u,v,w;
  11. }e[M];
  12. void adde(int i,int j,int k)
  13. {
  14. e[tot].u=i;e[tot].v=j;e[tot++].w=k;
  15. }
  16. int zhuliu(int root ,int vn)
  17. {
  18. int ans=;
  19. int cnt;
  20. while()
  21. {
  22. for(int i=;i<vn;i++)
  23. in[i]=INF,id[i]=-,vis[i]=-;
  24. for(int i=;i<tot;i++)
  25. {
  26. if(in[e[i].v]>e[i].w && e[i].u!=e[i].v)
  27. {
  28. pre[e[i].v]=e[i].u;
  29. in[e[i].v]=e[i].w;
  30. }
  31. }
  32. in[root]=;
  33. pre[root]=root;
  34. for(int i=;i<vn;i++)
  35. {
  36. ans+=in[i];
  37. if(in[i]==INF)//这一步可以看出是否存在这样一棵树形图,因此可以略去DFS
  38. return -;
  39. }
  40. cnt=;
  41. for(int i=;i<vn;i++)
  42. {
  43. if(vis[i]==-)
  44. {
  45. int t=i;
  46. while(vis[t]==-)
  47. {
  48. vis[t]=i;
  49. t=pre[t];
  50. }
  51. if(vis[t]!=i || t==root) continue;
  52. for(int j=pre[t];j!=t;j=pre[j])
  53. id[j]=cnt;
  54. id[t]=cnt++;
  55. }
  56. }
  57. if(cnt==) break;
  58. for(int i=;i<vn;i++)
  59. if(id[i]==-)
  60. id[i]=cnt++;
  61. for(int i=;i<tot;i++)
  62. {
  63. int u,v;
  64. u=e[i].u;
  65. v=e[i].v;
  66. e[i].u=id[u];
  67. e[i].v=id[v];
  68. e[i].w-=in[v];
  69. }
  70. vn=cnt;
  71. root=id[root];
  72. }
  73. return ans;
  74. }
  75.  
  76. struct Node
  77. {
  78. int a,b,c;
  79. }nd[N];
  80. int main()
  81. {
  82. //freopen("test.txt","r",stdin);
  83. int n,x,y,z,i,j,k,d;
  84. while(scanf("%d%d%d%d",&n,&x,&y,&z)!=EOF)
  85. {
  86. if(!n) break;
  87. tot=;
  88. for(i=;i<=n;i++)
  89. {
  90. scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].c);
  91. adde(,i,nd[i].c*x);
  92. }
  93. for(i=;i<=n;i++)
  94. {
  95. scanf("%d",&k);
  96. while(k--)
  97. {
  98. scanf("%d",&j);
  99. if(i==j) continue;
  100. d=abs(nd[i].a-nd[j].a)+abs(nd[i].b-nd[j].b)+abs(nd[i].c-nd[j].c);
  101. d*=y;
  102. if(nd[i].c<nd[j].c) d+=z;
  103. adde(i,j,d);
  104. }
  105. }
  106. int ans=zhuliu(,n+);
  107. if(ans==-) printf("poor XiaoA\n");
  108. else printf("%d\n",ans);
  109. }
  110. return ;
  111. }

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

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. using namespace std;
  5. const int N = , INF=0x3f3f3f3f;
  6. int Map[N][N];
  7. bool vis[N],f[N];
  8. //f是缩点标记,1表示该点已经被缩掉
  9. int pre[N];
  10. int zhuliu(int n)
  11. {
  12. int sum=;
  13. int i,j,k;
  14. for(i=;i<n;i++)
  15. {
  16. f[i]=;
  17. Map[i][i]=INF;
  18. }
  19. pre[]=;
  20. while()
  21. {
  22. //求最短弧集合E0
  23. for(i=;i<n;i++)
  24. {
  25. if(f[i]) continue;
  26. pre[i]=i;
  27. for(j=;j<n;j++)
  28. if(!f[j]&&Map[j][i]<Map[pre[i]][i]) pre[i]=j;
  29. if(pre[i]==i) return -; //没有入边,不存在最小树形图
  30. }
  31. //检查E0
  32. for(i=;i<n;i++)
  33. {
  34. if(f[i]) continue ;
  35. //从当前点开始找环
  36. for(j=;j<n;j++) vis[j]=;
  37. vis[]=;
  38. j=i;
  39. do
  40. {
  41. vis[j]=;
  42. j=pre[j];
  43. }
  44. while(!vis[j]) ;
  45. if(!j) continue; //没有找到环
  46. //收缩G中的有向环
  47. i=j;
  48. //将整个环的权值保存,累计入原图的最小树形图
  49. do
  50. {
  51. sum+=Map[pre[j]][j];
  52. j=pre[j];
  53. }
  54. while(j!=i) ;
  55. j=i;
  56. //对与环上的点有关的边,修改边权
  57. do
  58. {
  59. for(k=; k<n; k++)
  60. if(!f[k]&&Map[k][j]<INF&&k!=pre[j])
  61. Map[k][j]-= Map[pre[j]][j];
  62. j=pre[j];
  63. }
  64. while(j!=i) ;
  65. //缩点,将整个环缩成i号点,所有与环上的点有关的边转移到点i
  66. for(j=;j<n;j++)
  67. {
  68. if(j==i) continue;
  69. for(k=pre[i]; k!=i; k=pre[k])
  70. {
  71. if(Map[k][j]<Map[i][j]) Map[i][j] =Map[k][j];
  72. if(Map[j][k]<Map[j][i]) Map[j][i] =Map[j][k];
  73. }
  74. }
  75. //标记环上其他的点为被缩掉
  76. for(j=pre[i];j!=i;j=pre[j]) f[j] =;
  77. //当前环缩点结束,形成新的图G’,跳出继续求G’的最小树形图
  78. break;
  79. }
  80. //如果所有的点都被检查且没有环存在,现在的最短弧集合E0就是
  81. //最小树形图,累计如sum, 算法结束
  82. if(i==n)
  83. {
  84. for(i=;i<n;i++) if(!f[i]) sum+=Map[pre[i]][i];
  85. break;
  86. }
  87. }
  88. return sum;
  89. }
  90.  
  91. struct node
  92. {
  93. int a,b,c;
  94. }nd[N];
  95. int main()
  96. {
  97. //freopen("test.txt","r",stdin);
  98. int n,x,y,z,i,j,k,d;
  99. while(scanf("%d%d%d%d",&n,&x,&y,&z)!=EOF)
  100. {
  101. if(!n) break;
  102. for(i=;i<=n;i++)
  103. for(j=;j<i;j++)
  104. Map[j][i]=Map[i][j]=INF;
  105. for(i=;i<=n;i++)
  106. {
  107. scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].c);
  108. Map[][i]=nd[i].c*x;
  109. }
  110. for(i=;i<=n;i++)
  111. {
  112. scanf("%d",&k);
  113. while(k--)
  114. {
  115. scanf("%d",&j);
  116. if(i==j) continue;
  117. d=abs(nd[i].a-nd[j].a)+abs(nd[i].b-nd[j].b)+abs(nd[i].c-nd[j].c);
  118. d*=y;
  119. if(nd[i].c>=nd[j].c) d+=z;
  120. Map[i][j]=min(d,Map[i][j]);
  121. }
  122. }
  123. printf("%d\n",zhuliu(n+));
  124. }
  125. return ;
  126. }

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. 整理Webview加载缓慢的解决方案

    1.https://www.cnblogs.com/xinye/p/3144139.html 2.https://www.jianshu.com/p/95d4d73be3d1

  2. 在Android 上运行 openCV ,并做灰度变化的一个例子

    OpenCVImageProcessing1. 导入Opencv的 androrid SDK灰度算法 OpenCVImageProcessing 导入opencv Jar包,配置OpenCVLibra ...

  3. PAT_A1111#Online Map

    Source: PAT A1111 Online Map (30 分) Description: Input our current position and a destination, an on ...

  4. Mysql [Err] 1118 - Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535.

    对于越来越多的数据,数据库的容量越来越大,压缩也就越来越常见了.在我的实际工作中进行过多次压缩工作,也遇到多次问题,在此和大家分享一下. 首先,我们先说说怎么使用innodb的压缩. 第一,mysql ...

  5. 51nod1085 背包问题【动态规划】

    在N件物品取出若干件放在容量为W的背包里,每件物品的体积为W1,W2--Wn(Wi为整数),与之相对应的价值为P1,P2--Pn(Pi为整数).求背包能够容纳的最大价值. Input 第1行,2个整数 ...

  6. 企业版 Linux 附加软件包(EPEL)

    企业版 Linux 附加软件包(以下简称 EPEL)是一个由特别兴趣小组创建.维护并管理的,针对 红帽企业版 Linux(RHEL)及其衍生发行版(比如 CentOS.Scientific Linux ...

  7. 【3】Django创建第一个项目

    天地所以能长且久者,以其不自生,故能长生. --老子<道德经> 写在前面:Django在学习的过程中,我们会参考官方文档,从两部分进行讲解,第一部分主要是一个入门项目的搭建开发,第二部分是 ...

  8. Solr数据不同步

    Solr配置了集群,本地有253和254,2个独立的Solr服务.  同一个页面的图片,刷新2次,图片地址不一样,最后查明,后台数据源Solr1和Solr2的数据不一致.    第1步推测:本地缓存, ...

  9. Java代码模拟http请求的两种方式

    z这里用百度地图的逆地理编码接口为例, 第一种方式:(通过jdk中的java.net包) 引入工具类 import java.net.URL; import java.net.URLConnectio ...

  10. elasticsearch 文档阅读笔记(三)

    文档 elasticsearch是通过document的形式存储数据的,个人理解文档就是一条数据一个对象 我们添加索引文档中不仅包含了数据还包含了元数据 比如我们为一个数据添加索引 文档中不仅有jso ...