斯坦那树

百度释义

斯坦纳树问题是组合优化问题,与最小生成树相似,是最短网络的一种。最小生成树是在给定的点集和边中寻求最短网络使所有点连通。而最小斯坦纳树允许在给定点外增加额外的点,使生成的最短网络开销最小。

即最小斯坦那树即为并非选择所有的结点,而是选择一部分结点,为保证它们连通,且求解最小开销

题解

斯坦那树模板

发现直接表示点的存在性没有意义

设函数 \(f[i][state]\) 表示:对于点 \(i\),其它结点与其连通情况

那么有两种转移

其一、由其子集转移

\[f[i][state] = \min\limits_{sub \in state} \{f[i][sub] + f[i][\complement_{state}sub] - value_i\}
\]

之所以要减去 \(value_i\) 是因为会算重

附:枚举子集的方法

for (int sub = state & (state - 1); sub; sub = (sub - 1) & state)

其二、由相邻当前状态下结点转移

\[f[i][state] = \min\limits_{state_p = true} \{f[p][state] + value_i\}
\]

发现很像三角形不等式,故考虑 \(SPFA\) 转移

总复杂度 \(O (n3^n + kE2^n)\),\(3^n\) 为枚举子集总复杂度

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue> using namespace std; const int MAXN = 10 + 5;
const int MAXM = 1 << 10; const int INF = 0x3f3f3f3f; const int NextX[4]= {- 1, 0, 0, 1}, NextY[4]= {0, - 1, 1, 0}; int N, M;
int Map[MAXN][MAXN]= {0}; struct preSt {
int x, y;
int state; preSt (int fx = 0, int fy = 0, int fs = 0) :
x (fx), y (fy), state (fs) {}
} ; int f[MAXN][MAXN][MAXM];
preSt pre[MAXN][MAXN][MAXM];
int cnt = 0; queue<pair<int, int> > que;
void SPFA (int state) {
while (! que.empty()) {
pair<int, int> top = que.front();
que.pop(); int x = top.first, y = top.second;
for (int i = 0; i < 4; i ++) {
int tx = x + NextX[i];
int ty = y + NextY[i];
if (tx < 1 || tx > N || ty < 1 || ty > M)
continue;
if (f[x][y][state] + Map[tx][ty] < f[tx][ty][state]) {
f[tx][ty][state] = f[x][y][state] + Map[tx][ty];
pre[tx][ty][state] = preSt (x, y, state);
que.push(make_pair (tx, ty));
}
}
}
} int tag[MAXN][MAXN]= {0};
void traceback (int x, int y, int state) {
if (! x || ! y)
return ;
tag[x][y] = 1;
preSt pr = pre[x][y][state];
traceback (pr.x, pr.y, pr.state);
if (pr.x == x && pr.y == y)
traceback (pr.x, pr.y, state - pr.state);
} int getnum () {
int num = 0;
char ch = getchar (); while (! isdigit (ch))
ch = getchar ();
while (isdigit (ch))
num = (num << 3) + (num << 1) + ch - '0', ch = getchar (); return num;
} int main () {
memset (f, 0x3f, sizeof (f));
N = getnum (), M = getnum ();
int px, py;
for (int i = 1; i <= N; i ++)
for (int j = 1; j <= M; j ++) {
Map[i][j] = getnum ();
if (! Map[i][j]) {
cnt ++, f[i][j][1 << (cnt - 1)] = 0;
px = i, py = j;
}
}
int limit = (1 << cnt) - 1;
for (int state = 1; state <= limit; state ++) {
for (int i = 1; i <= N; i ++)
for (int j = 1; j <= M; j ++) {
for (int sub = state & (state - 1); sub; sub = (sub - 1) & state) // from subset
if (f[i][j][sub] + f[i][j][state - sub] - Map[i][j] < f[i][j][state]) {
f[i][j][state] = f[i][j][sub] + f[i][j][state - sub] - Map[i][j];
pre[i][j][state] = preSt (i, j, sub);
}
if (f[i][j][state] < INF)
que.push(make_pair (i, j));
}
SPFA (state); // from other nodes
}
traceback (px, py, limit);
printf ("%d\n", f[px][py][limit]);
for (int i = 1; i <= N; i ++) {
for (int j = 1; j <= M; j ++) {
if (! Map[i][j])
putchar ('x');
else {
tag[i][j] ? putchar ('o') : putchar ('_');
}
}
puts ("");
} return 0;
} /*
4 4
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0
*/

[WC2008]游览计划 「斯坦那树模板」的更多相关文章

  1. BZOJ_2595_[Wc2008]游览计划_斯坦纳树

    BZOJ_2595_[Wc2008]游览计划_斯坦纳树 题意: 分析: 斯坦纳树裸题,有几个需要注意的地方 给出矩阵,不用自己建图,但枚举子集转移时会算两遍,需要减去当前点的权值 方案记录比较麻烦,两 ...

  2. BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*

    BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...

  3. 【BZOJ2595_洛谷4294】[WC2008]游览计划(斯坦纳树_状压DP)

    上个月写的题qwq--突然想写篇博客 题目: 洛谷4294 分析: 斯坦纳树模板题. 简单来说,斯坦纳树问题就是给定一张有边权(或点权)的无向图,要求选若干条边使图中一些选定的点连通(可以经过其他点) ...

  4. bzoj 2595 [Wc2008]游览计划(斯坦纳树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2595 [题意] 给定N*M的长方形,选最少权值和的格子使得要求的K个点连通. [科普] ...

  5. BZOJ2595 WC2008游览计划(斯坦纳树)

    斯坦纳树板子题. 考虑状压dp,设f[i][j][S]表示当前在点(i,j)考虑转移,其所在的联通块包含的关键点集(至少)为S的答案. 转移时首先枚举子集,有f[i][j][S]=min{f[i][j ...

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

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

  7. BZOJ.2595.[WC2008]游览计划(DP 斯坦纳树)

    题目链接 f[i][s]表示以i为根节点,当前关键点的连通状态为s(每个点是否已与i连通)时的最优解.i是枚举得到的根节点,有了根节点就容易DP了. 那么i为根节点时,其状态s的更新为 \(f[i][ ...

  8. 【BZOJ2595】[Wc2008]游览计划 斯坦纳树

    [BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为 ...

  9. 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)

    2595: [Wc2008]游览计划 Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 1572  Solved: 7 ...

随机推荐

  1. ElasticSearch 2 (32) - 信息聚合系列之范围限定

    ElasticSearch 2 (32) - 信息聚合系列之范围限定 摘要 到目前为止我们看到的所有聚合的例子都省略了搜索请求,完整的请求就是聚合本身. 聚合与搜索请求同时执行,但是我们需要理解一个新 ...

  2. Linux命令(六) 查看文件 cat tac more less tail

    如果要查看文件,使用 cat  less  tac   tail  和 more 中的任意一个即可. 1.cat 使用 cat 命令查看文件时会显示整个文件的内容,注意cat只能查看文本文件的内容,如 ...

  3. bzip2 以及 tar 压缩/解压缩/.打包等工具软件

    1. bzip2 命令 基础格式: bzip2 [Options] file1 file2 file3 指令选项:(默认功能为压缩) -c //将输出写至标准输出 -d //进行解压操作 -v //输 ...

  4. SSH-keygen用法

    很多朋友在用github管理项目的时候,都是直接使用https url克隆到本地,当然也有有些人使用 SSH url 克隆到本地.然而,为什么绝大多数人会使用https url克隆呢? 这是因为,使用 ...

  5. windows10中远程登录ubuntu16.04的桌面

      1. 安装xrdp sudo apt-get install xrdp 2. 安装vnc4server sudo apt-get install vnc4server tightvncserver ...

  6. 【题解】 [HNOI2009] 最小圈 (01分数规划,二分答案,负环)

    题目背景 如果你能提供题面或者题意简述,请直接在讨论区发帖,感谢你的贡献. 题目描述 对于一张有向图,要你求图中最小圈的平均值最小是多少,即若一个圈经过k个节点,那么一个圈的平均值为圈上k条边权的和除 ...

  7. bzoj1040 骑士

    Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火 ...

  8. 【BZOJ1028】[JSOI2007]麻将(贪心)

    [BZOJ1028][JSOI2007]麻将(贪心) 题面 BZOJ 洛谷 题解 感觉好久没打过麻将了,似乎都快不会打了. 这个数据范围看着就觉得是\(O(n^2m)\). 那么就枚举听哪张牌,然后枚 ...

  9. 普通平衡树Treap(含旋转)学习笔记

    浅谈普通平衡树Treap 平衡树,Treap=Tree+heap这是一个很形象的东西 我们要维护一棵树,它满足堆的性质和二叉查找树的性质(BST),这样的二叉树我们叫做平衡树 并且平衡树它的结构是接近 ...

  10. Problem C: 多线程 解题报告

    Problem C: 多线程 Description 多线程是一种常见的加速手段,利用多个线程同时处理不同的任务可以一定程度上减少总耗时,达到提高效率的目的.然而,多个线程间的执行顺序是完全不可控的, ...