传送门

题意:

给出\(n\)个重要点,还有其余\(m\)个点,\(p\)条边。

现在要在这\(n+m\)个点中挖几口水井,每个地方的费用为\(w_i\)。连接边也有费用。

问使得这\(n\)个地点都有水井(或直接、间接与水井相连)的最小代价。

思路:

有点巧妙。。建立一个虚点连向所有点,边权为\(w_i\)。然后直接求以\(0\)为根的斯坦纳树即可,最后再子集\(dp\)一下就行。

原理就是,此时这\(n\)个点连通,并且以\(0\)为根,脑补一下即可发现:要么直接与\(0\)相连,要么间接相连,直接相连就是这里挖井,间接相连的话就是通过其它地方引水。

代码如下:

  1. /*
  2. * Author: heyuhhh
  3. * Created Time: 2019/11/27 14:23:05
  4. */
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <vector>
  8. #include <cmath>
  9. #include <set>
  10. #include <map>
  11. #include <iomanip>
  12. #include <queue>
  13. #include <cstdio>
  14. #include <cstring>
  15. #define MP make_pair
  16. #define fi first
  17. #define se second
  18. #define sz(x) (int)(x).size()
  19. #define all(x) (x).begin(), (x).end()
  20. #define INF 0x3f3f3f3f
  21. #define Local
  22. #ifdef Local
  23. #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  24. void err() { std::cout << '\n'; }
  25. template<typename T, typename...Args>
  26. void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  27. #else
  28. #define dbg(...)
  29. #endif
  30. void pt() {std::cout << '\n'; }
  31. template<typename T, typename...Args>
  32. void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
  33. using namespace std;
  34. typedef long long ll;
  35. typedef pair<int, int> pii;
  36. //head
  37. const int N = 1010, M = 10005, P = 6;
  38. int n, m, p;
  39. struct Edge {
  40. int v, w, next;
  41. }e[M << 1];
  42. int head[N], tot;
  43. void adde(int u, int v, int w) {
  44. e[tot].v = v; e[tot].w = w; e[tot].next = head[u]; head[u] = tot++;
  45. }
  46. int dp[N][1 << P];
  47. queue <int> q;
  48. bool in[N];
  49. void spfa(int s) {
  50. while(!q.empty()) {
  51. int u = q.front(); q.pop(); in[u] = 0;
  52. for(int i = head[u]; i != -1; i = e[i].next) {
  53. int v = e[i].v;
  54. if(dp[v][s] > dp[u][s] + e[i].w) {
  55. dp[v][s] = dp[u][s] + e[i].w;
  56. if(!in[v]) q.push(v), in[v] = 1;
  57. }
  58. }
  59. }
  60. }
  61. int g[1 << P];
  62. void run(){
  63. memset(head, -1, sizeof(head)); tot = 0;
  64. for(int i = 1; i <= n + m; i++) {
  65. int w; cin >> w;
  66. adde(0, i, w);
  67. adde(i, 0, w);
  68. }
  69. for(int i = 1; i <= p; i++) {
  70. int u, v, w; cin >> u >> v >> w;
  71. adde(u, v, w); adde(v, u, w);
  72. }
  73. memset(dp, INF, sizeof(dp));
  74. memset(g, INF, sizeof(g));
  75. for(int i = 1; i <= n; i++) {
  76. dp[i][1 << (i - 1)] = 0;
  77. }
  78. int lim = (1 << n);
  79. for(int S = 1; S < lim; S++) {
  80. for(int i = 0; i <= n + m; i++) {
  81. for(int s = (S - 1) & S; s; s = (s - 1) & S) {
  82. dp[i][S] = min(dp[i][S], dp[i][s] + dp[i][S - s]);
  83. }
  84. if(dp[i][S] < INF) q.push(i), in[i] = 1;
  85. }
  86. spfa(S);
  87. g[S] = dp[0][S];
  88. }
  89. for(int S = 1; S < lim; S++) {
  90. for(int s = (S - 1) & S; s; s = (s - 1) & S) {
  91. g[S] = min(g[S], g[s] + g[S - s]);
  92. }
  93. }
  94. cout << g[lim - 1] << '\n';
  95. }
  96. int main() {
  97. ios::sync_with_stdio(false);
  98. cin.tie(0); cout.tie(0);
  99. cout << fixed << setprecision(20);
  100. while(cin >> n >> m >> p) run();
  101. return 0;
  102. }

【hdu3311】Dig The Wells(斯坦纳树+dp)的更多相关文章

  1. HDU - 3311: Dig The Wells (斯坦纳树)

    题意:给你n个寺庙,m个村庄,p条路,现在你要在这n+m个位置中选出若干个位置打井,每个位置打井的费用会告诉你,同时p条路也有修建费用,现在每个寺庙都住着一个和尚,问你最小的费用让这n个和尚都能喝上水 ...

  2. 【bzoj4006】[JLOI2015]管道连接(斯坦纳树+dp)

    题目链接 题意: 给出\(n\)个点,\(m\)条边,同时给出\(p\)个重要的点以及对应特征. 现在要选出一些边,问使得这\(p\)个所有特征相同的点相连,问最小代价. 思路: 斯坦纳树的应用场景一 ...

  3. HDU 4085 斯坦纳树+DP

    https://cn.vjudge.net/problem/HDU-4085 给你n,m,k ,分别表示有n个点,m条边,每条边有一个权值,表示修复这条边需要的代价 从前k个点中任取一个使其和后k个点 ...

  4. [WC2008]游览计划(斯坦纳树)

    [Luogu4294] 题解 : 斯坦纳树 \(dp[i][j]\) 表示以\(i\)号节点为根,当前状态为\(j\)(与\(i\)连通的点为\(1\)) 当根\(i\)不改变时状态转移方程是: \( ...

  5. HDU 3311 Dig The Wells(斯坦纳树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3311 [题意] 给定k座庙,n个其他点,m条边,点权代表挖井费用,边权代表连边费用,问使得k座庙里 ...

  6. 【BZOJ2595】游览计划(状压DP,斯坦纳树)

    题意:见题面(我发现自己真是越来越懒了) 有N*M的矩阵,每个格子有一个值a[i,j] 现要求将其中的K个点(称为关键点)用格子连接起来,取(i,j)的费用就是a[i,j] 求K点全部连通的最小花费以 ...

  7. hdu4085 Peach Blossom Spring 斯坦纳树,状态dp

    (1)集合中元素表示(1<<i), i从0开始 (2)注意dp[i][ss] = min(dp[i][ss], dp[i][rr | s[i]] + dp[i][(ss ^ rr) | s ...

  8. bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...

  9. BZOJ 2595: [Wc2008]游览计划 [DP 状压 斯坦纳树 spfa]【学习笔记】

    传送门 题意:略 论文 <SPFA算法的优化及应用> http://www.cnblogs.com/lazycal/p/bzoj-2595.html 本题的核心就是求斯坦纳树: Stein ...

随机推荐

  1. Windows 7下Node.js Web开发环境搭建笔记

    Node.js是什么? 我们看看百科里怎么说的?JavaScript是一种运行在浏览器的脚本,它简单,轻巧,易于编辑,这种脚本通常用于浏览器的前端编程,但是一位开发者Ryan有一天发现这种前端式的脚本 ...

  2. read write方式打开PHYSICAL STANDBY,闪回和还原测试

    以下大部分都在STANDBY执行,主库执行(两次)的会提示 [STANDBY read write方式打开测试]检查standby状态SQL> SELECT NAME,DATABASE_ROLE ...

  3. python包matplotlib绘制图像

    使用matplotlib绘制图像 import matplotlib.pyplot as plt from matplotlib.pyplot import MultipleLocator impor ...

  4. Go package: strings

    Go strings Go 的 strings 包中包含许多处理字符串的函数 官方文档:https://golang.org/pkg/strings/ 前缀.后缀 判断字符串前缀.后缀 // 判断字符 ...

  5. Ubuntu sudo 免密码

    sudo visudo 这里默认打开的是 nano 编辑器,不习惯可以把默认编辑器换成 vim, 参考 Ubuntu 修改默认编辑器 test ALL=NOPASSWD: ALL

  6. 《转》sql处理百万级以上的数据提高查询速度的方法

    处理百万级以上的数据提高查询速度的方法: 1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考 ...

  7. css文本省略号

    这里记录下如何用CSS实现单行.多行文本溢出容器的时候用省略号代替溢出部分. 单行文本溢出容器时显示省略号的CSS实现方法 /* 规定当内容溢出元素框(容器)时隐藏 */ overflow: hidd ...

  8. Sql 代码规范说明

    对于程序工作者来说,代码的阅读必不可少,好的代码让人读起来一目了然.神清气爽,做代码调试也可以很开的捋顺逻辑定位问题,但是如果遇到一些可读性较差,毫无规矩可言的代码,那真的比吃了翔都难受啊,如果再让你 ...

  9. VS 自动创建带增删查改的MVC网站

    VS 自动创建带增删查改的MVC网站 MVC.Net教程   废话放在前头,说一下这个文章的缘起某天某妹纸找我,说这个MVC的创建不太会,要记一下controllers.models.还有页面引用的东 ...

  10. layui 使用随记

    layui confir使用 不显示右上角关闭按钮 针对提示框内按钮指定操作 layer.confirm("这里填写提示信息", {closeBtn:0,icon: 0, titl ...