业界萌新对斯坦纳树的小结

业界萌新对斯坦纳树的小结

0.简介

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

                                                                                                                                                                           ——百度百科

简单来讲,斯坦纳树问题一般就是给定一个n个点m条边的带非负权无向图,其中有k个关键点,要求选取一个子图,让所有关键点联通,而最小斯坦纳树则在斯坦纳树的前提下,让总费用最小

在此推荐一位学长的文章,写得很不错:详解斯坦纳点及斯坦纳树及模版归纳总结。

 

1.最小斯坦纳树的求解方法

斯坦纳树只要求k个关键点联通,显然不能够直接用最小生成树的方法解决。

  • 结论:最优解的方案一定会选取一棵树。
  • 证明:可行解显然是一个连通图,而如果图上存在一个环,费用为C。我们可以将其中最长的一条边去掉,使得新费用C'=C-len,由于len\in \mathbb{Z}^{+},所以C'<=C。因此只会选取一棵树。

这样选取一棵树求最优解的问题,常见的思路是DP

 

2.具体实现

2.1状态  

DP[i][state]   表示以i为根,关键点的选取状态为 state 的最优费用。

2.2转移

两重转移方程:

第一重转移,更新新的选取状态:f[i][state]=min(f[i][s1]+f[i][s2]) , s1,s2\subseteq state

第二重转移,松弛新的选取状态:f[i][state]=min(f[j][state]+len[j][i])

由于之后的选取状态会由第一重转移更新,所以只需要对当前的选取状态进行松弛即可。

第一重转移直接DP,第二重转移用SPFA松弛

(PS:一般出题人不会在此处卡SPFA,但如果路遇毒瘤出题人黑心卡SPFA,还是用dijstra吧)。

时间复杂度显然:O(3^kn+c2^kE),c是SPFA的常数,E是边数。

2.3细节与技巧:

 

  • 倘若每一次都SPFA全图松弛会产生大量冗余运算,SPFA只需要对当前层节点进行松弛。
  • 子集枚举时可以用:for\;(s=S\;and\;(S-1);s;s=(s-1)\;and\;S)   and表示位运算的与。

3.一个例题:[WC2008][luoguP4294]游览计划

题目描述

从未来过绍兴的小D有幸参加了Winter Camp 2008,他被这座历史名城的秀丽风景所吸引,强烈要求游览绍兴及其周边的所有景点。

主办者将绍兴划分为N行M列(N×M)个分块,如下图(8×8):

景点含于方块内,且一个方块至多有一个景点。无景点的方块视为路。

为了保证安全与便利,主办方依据路况和治安状况,在非景点的一些方块内安排不同数量的志愿者;在景点内聘请导游(导游不是志愿者)。在选择旅游方案时,保证任意两个景点之间,存在一条路径,在这条路径所经过的每一个方块都有志愿者或者该方块为景点。既能满足选手们游览的需要,又能够让志愿者的总数最少。

例如,在上面的例子中,在每个没有景点的方块中填入一个数字,表示控制该方块最少需要的志愿者数目:

图中用深色标出的方块区域就是一种可行的志愿者安排方案,一共需要20名志愿者。由图可见,两个相邻的景点是直接(有景点内的路)连通的(如沈园和八字桥)。

现在,希望你能够帮助主办方找到一种最好的安排方案。

输入输出格式

输入格式:

第一行有两个整数,N和M,描述方块的数目。

接下来N行,每行有M个非负整数,如果该整数为0,则该方块为一个景点;

否则表示控制该方块至少需要的志愿者数目。相邻的整数用(若干个)空格隔开,

行首行末也可能有多余的空格。

输出格式:

由N+1行组成。第一行为一个整数,表示你所给出的方案中安排的志愿者总数目。

接下来N行,每行M个字符,描述方案中相应方块的情况:

'_'(下划线)表示该方块没有安排志愿者;

'o'(小写英文字母o)表示该方块安排了志愿者;

'x'(小写英文字母x)表示该方块是一个景点;

注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不一致(任何一行中,多余的空格都不允许出现),都可能导致该测试点不得分。

输入输出样例

输入样例#1:

4 4
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0

输出样例#1:

6
xoox
___o
___o
xoox

说明

所有的 10 组数据中 N, M ,以及景点数 K 的范围规定如下

输入文件中的所有整数均不小于 0 且不超过 2^16

感谢@panda_2134 提供Special Judge

 

Solution

显然的最小斯坦纳树问题,f[i][j][state]  表示以i,j这个格子为根,关键点选取状态为state的最小个数。

#include<bits/stdc++.h>
using namespace std;
const int MAXN=12;
const int MAXS=2005;
const int dx[4]={0,0,-1,1};
const int dy[4]={1,-1,0,0};
const int INF=0x3f3f3f3f;
int n,m,cnt,xt,yt;
int f[MAXN][MAXN][MAXS],c[MAXN][MAXN],p[MAXN][MAXN];
struct node{int x,y,s; } pre[MAXN][MAXN][MAXS];
bool ans[MAXN][MAXN],vis[MAXN][MAXN][MAXS];
queue<node> Q;
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }return x*f;
}
void find(int x,int y,int s)
{ans[x][y]=1;node q=pre[x][y][s];if (q.x==0) return;find(q.x,q.y,q.s);if (q.x==x&&q.y==y) find(x,y,(s-q.s)|p[x][y]);
}
void spfa()
{while (!Q.empty()){node q=Q.front(); Q.pop();int x=q.x,y=q.y,s=q.s;vis[x][y][s]=0;for (int i=0;i<4;i++){int xx=x+dx[i],yy=y+dy[i],ss=s|p[xx][yy];if (xx<1||xx>n||yy<1||yy>m) continue;if (f[x][y][s]+c[xx][yy]<f[xx][yy][ss]) {f[xx][yy][ss]=f[x][y][s]+c[xx][yy];pre[xx][yy][ss]=(node){x,y,s};if (s==ss&&(!vis[xx][yy][ss])) vis[xx][yy][ss]=1,Q.push((node){xx,yy,ss});}}}
}
int main()
{n=read(),m=read(),cnt=0;memset(f,INF,sizeof f);for (int i=1;i<=n;i++)for (int j=1;j<=m;j++){c[i][j]=read();if (!c[i][j]) p[i][j]=(1<<(cnt++)),xt=i,yt=j,f[i][j][p[i][j]]=0; }for (int S=1;S<(1<<cnt);S++){for (int i=1;i<=n;i++)for (int j=1;j<=m;j++)if ((S&p[i][j]) || !p[i][j]){for (int s=(S-1)&S;s;s=(s-1)&S){int t=f[i][j][ (S-s)|p[i][j] ]+f[i][j][ s|p[i][j] ]-c[i][j]; //(i,j)这一点重复计算了,把c[i][j]消去。 if (f[i][j][S]>t) f[i][j][S]=t,pre[i][j][S]=(node){i,j,s|p[i][j]};//更新f[i][j][S],并记录路径。 }if (f[i][j][S]<INF) vis[i][j][S]=1,Q.push((node){i,j,S}); }spfa();}printf("%d\n",f[xt][yt][(1<<cnt)-1]);find(xt,yt,(1<<cnt)-1);for (int i=1;i<=n;i++){for (int j=1;j<=m;j++)if (p[i][j]) putchar('x');else if (ans[i][j]) putchar('o');else putchar('_');puts("");}return 0;
}

 

4.一些斯坦纳树题

[THUSC2017]巧克力 斯坦纳树+随机+二分

[BZOJ 4006] 管道连接

[hdu 3331]Trip the Lights Fantastic

[HDU 4085] Peach Blossom Spring

[ZOJ 3613] Wormhole Transport

 

5.萌新的总结

用状压DP解决最小斯坦纳树的时间复杂度对于k是指数级别的,所以一般的最小斯坦纳数问题中,k的范围在10左右。

斯坦纳树实现并不难,思维难度也不高,还是一个很实用的算法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315900.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cf1208E. Let Them Slide

cf1208E. Let Them Slide 题意&#xff1a; 都放在一个长度为W的框里面。有n个序到&#xff0c;第i个序列的长度是1。这些序到并排放在一起&#xff0c;每一个序列都放在一个长度为w的框里 这些序列可以在框里面滑动&#xff0c;但是不能划出框。 对于每一个位置&#xff0…

结合eShopOnWeb全面认识领域模型架构

一.项目分析在上篇中介绍了什么是"干净架构"&#xff0c;DDD符合了这种干净架构的特点&#xff0c;重点描述了DDD架构遵循的依赖倒置原则&#xff0c;使软件达到了低藕合。eShopOnWeb项目是学习DDD领域模型架构的一个很好案例&#xff0c;本篇继续分析该项目各层的职…

SOS_dp算法

Codeforces博客 简介&#xff1a; 前置知识&#xff1a;状压dp Sum over Subsets dynamic programming&#xff0c;简称Sos dp,状压dp的一种 用一个列题引出SOS dp&#xff1a; 给你一个由2N2^N2N个整数组成的确定数组A&#xff0c;我们需要计算对于任意的x&#xff0c;F(x)所…

微软开源Bing搜索背后的关键算法

微软今天宣布开源了一项 Bing 搜索背后的关键算法 —— SPTAG&#xff0c;它使 Bing 能够快速将搜索结果返回给用户。仅在几年前&#xff0c;网络搜索很简单&#xff0c;用户输入几个关键词然后浏览结果页面。现如今&#xff0c;这些用户可能会在手机上拍照并将其放入搜索框中&…

Stern-Brocot Tree

Stern-Brocot Tree 0.简介 Stern-Brocot Tree&#xff0c;俗称SB树&#xff08;滑稽&#xff09;。它能够表示出所有的最简分数&#xff0c;如下图。 1.一些规律 显然&#xff0c;对于两个相邻的最简分数 可以得到另一个最简分数 这样就可以在Stern-Brocot Tree上表示出所有…

FWT(快速沃尔什变换)

文章目录引入&#xff1a;or卷积and卷积xor卷积IFWT模板&#xff1a;例题&#xff1a;引入&#xff1a; FFT/NTT是用来解决∑ijkA[i]B[j]\sum_{ijk}A[i]B[j]∑ijk​A[i]B[j]的式子 而FWT是用来解决Ci∑j⊕kiAjBkC_i\sum_{j⊕ki}A_jB_kCi​∑j⊕ki​Aj​Bk​ ​ FWT是一种用于处…

教你自制.NET Core Global Tools

点击上方蓝字关注“汪宇杰博客”命令行是程序员装逼利器&#xff0c;.NET Core也可以写命令行程序&#xff0c;但是如何分发给其他程序员使用&#xff0c;一直是个问题。现在&#xff0c;有了.NET Core Global Tools&#xff0c;可以很方便的解决分发问题&#xff0c;我们来看看…

三点间LCA

三点间LCA 1.直接上题——jzoj5883. 【NOIP2018模拟A组9.25】到不了 Dscription wy 和 wjk 是好朋友。 今天他们在一起聊天&#xff0c;突然聊到了以前一起唱过的《到不了》。 “说到到不了&#xff0c;我给你讲一个故事吧。” “嗯&#xff1f;” “从前&#xff0c;神和凡人…

微软拥抱开源,Win10为啥要引入真Linux4.X内核?

来源 | 异步 | 文末赠书2019 年微软 Build 开发者大会在雷德蒙德召开。继将 Bash shell、原生 OpenSSH、WSL 引入 Windows&#xff0c;以及在微软商店提供 Ubuntu、SUSE Linux 和 Fedora 等发行版&#xff0c;微软又宣布了一个重大的决定 —— 将完整的 Linux 内核引入 Windows…

F.孤独(牛客小白月赛39)

F.孤独&#xff08;牛客小白月赛39&#xff09; 题意&#xff1a; 给定一棵树&#xff0c;寻找一个路径&#xff0c;将断掉所有与这个路径上的点相连的边&#xff0c;使得剩下的最大连通块的大小最小 题解&#xff1a; 这题有点印象&#xff0c;感觉做过&#xff0c;至少这…

分布式 - 分布式系统的特点

20世纪60年代&#xff0c;IBM研发了System 360架构大型机&#xff0c;与同时期的波音707、福特汽车誉为商业三大成就&#xff0c;凭借其卓越的性能和良好的稳定性&#xff0c;开启了大型机的时代&#xff0c;诞生了非常多的集中式系统&#xff0c;采用单机架构&#xff0c;有非…

[WC2011][BZOJ2115] Xor

BZOJ2115 Xor 题目描述&#xff1a; 题目大意&#xff1a; 给定一张 n 个点 m 条边的无向带权连通图&#xff0c;求一条从点 1 到点 n 的路径&#xff0c;使得经过的边权异或和最大。 路径可以经过重复点和重复边&#xff0c;当一条边被重复经过时也会相应地被 xor 多次。 s…

.NET Core 3.0 可回收程序集加载上下文

.NET诞生以来&#xff0c;程序集的动态加载和卸载都是一个Hack的技术&#xff0c;之前的NetFx都是使用AppDomain的方式去加载程序集&#xff0c;然而AppDomain并没有提供直接卸载一个程序集的API&#xff0c;而是要卸载整个AppDomain才能卸载包含在其中的所有程序集。然而卸载整…

ADPC2-G 希望

希望 题意&#xff1a; 有A&#xff0c;B两棵树&#xff0c;对于一个1到n的全排列a[i],让树A中的点i和树B的节点a[i]连一条边&#xff0c;希望指数&#xff1a;两棵树和新加入的边构成的图中&#xff0c;环长为m的环的个数。数组a[]可以任意交换位置&#xff0c;且任意&#…

.Net Core中依赖注入服务使用总结

一、依赖注入引入依赖注入的目的是为了解耦和。说白了就是面向接口编程&#xff0c;通过调用接口的方法&#xff0c;而不直接实例化对象去调用。这样做的好处就是如果添加了另一个种实现类&#xff0c;不需要修改之前代码&#xff0c;只需要修改注入的地方将实现类替换。上面的…

[BZOJ3944] Sum

[BZOJ3944] Sum 题目描述&#xff1a; solution 裸的杜教筛。 唯一的坑点在于卡常。 似乎ans1和ans2都杜教筛超时了。 然而用杜教筛求出ans2&#xff0c;并用求出ans1不超时&#xff1f;&#xff01;&#xff1f;。 ​ ​ ​ #include<bits/stdc.h> using namespac…

SuperSocket 2.0 Preview1 发布,.NET Socket服务器框架

今天&#xff0c;SuperSocket的作者发布了2.0版本的第一个预览版。SuperSocket 2.0 是一个经过全新设计的&#xff0c;第一个完全基于.NET Core的版本。作者正在积极尝试提供更简单易用的API的同时&#xff0c;尽量保证与老版本相似的原汁原味的开发体验。新的版本中亦删除了一…

[LG P2519][BZOJ2298][HAOI2011]problem a

[LG P2519][BZOJ2298][HAOI2011]problem a 题目描述 一次考试共有n个人参加 第i个人说&#xff1a;"有ai个人分数比我高&#xff0c;bi个人分数比我低。" 问最少有几个人没有说真话(可能有相同的分数) 输入输出格式 输入格式&#xff1a; 第一行一个整数n&…

跟我学: 使用 fireasy 搭建 asp.net core 项目系列之一 —— 开篇

fireasy 面世都有六个年头了&#xff0c;至今依旧是默默无闻&#xff0c;知道它的人可能仅限于本人朋友圈内的人士。本人也在写一本关于如何使用该框架的书籍&#xff0c;但苦于事务繁忙&#xff0c;至今也才写了一半&#xff0c;可以说最为实用最为核心的部分&#xff0c;仍然…

某谷 P1654 OSU!

某谷 P1654 OSU! 题目背景 原 《产品排序》 参见P2577 题目描述 osu 是一款群众喜闻乐见的休闲软件。 我们可以把osu的规则简化与改编成以下的样子: 一共有n次操作&#xff0c;每次操作只有成功与失败之分&#xff0c;成功对应1&#xff0c;失败对应0&#xff0c;n次操作…