BZOJ 2595: [Wc2008]游览计划 [DP 状压 斯坦纳树 spfa]【学习笔记】
题意:略
http://www.cnblogs.com/lazycal/p/bzoj-2595.html
本题的核心就是求斯坦纳树:
Steiner Tree:
Given an undirected graph with non-negative edge weights and a subset of vertices, usually referred to as terminals,
the Steiner tree problem in graphs requires a tree of minimum weight that contains all terminals (but may include additional vertices).
也就是对于给定的点集求一颗包含他的最小生成树(可以包含额外的点)
$ST$是$NPC$问题,规模小的情况可以使用状压$DP$解决
$f[i][s]$表示根在$i$,连通的点集为$s$的(仅包括给定点集中的点)的最小花费
有两种转移:
对于点权的情况(边权类似):
$f[i][s]=min{f[i][s']+f[i][s-s']-val[i]}$,划分成两个子集,具有阶段性普通$DP$就可以
$f[i][s]=min{f[i'][s]+val[i]}$,从一颗树扩展而来,阶段性不明显,但满足三角不等式,使用$spfa$求解
那么过程就很清楚了
- 从小到大枚举集合和点
- 第一种转移枚举子集
- 第二种转移对当前集合使用spfa
然后就到黄学长哪里仿写了份模板
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #include <cmath>
- #include <queue>
- using namespace std;
- #define pii pair<int,int>
- #define MP make_pair
- #define fir first
- #define sec second
- typedef long long ll;
- const int N=,S=(<<)+,INF=1e9;
- inline int read(){
- char c=getchar();int x=,f=;
- while(c<''||c>''){if(c=='-')f=-;c=getchar();}
- while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
- return x*f;
- }
- int n,m,k,a[N][N];
- int f[N][N][S];
- struct Path{
- int i,j,s;
- Path(){}
- Path(int a,int b,int c):i(a),j(b),s(c){}
- }pre[N][N][S];
- queue<pii> q;
- bool inq[N][N];
- int dx[]={,-,,},dy[]={,,,-};
- void spfa(int s){
- while(!q.empty()){
- int x=q.front().fir,y=q.front().sec;
- inq[x][y]=;q.pop();
- for(int k=;k<;k++){
- int i=x+dx[k],j=y+dy[k];
- if(i<||i>n||j<||j>m) continue;
- if(f[i][j][s]>f[x][y][s]+a[i][j]){
- f[i][j][s]=f[x][y][s]+a[i][j];
- pre[i][j][s]=Path(x,y,s);
- if(!inq[i][j])
- q.push(MP(i,j)),inq[i][j]=;
- }
- }
- }
- }
- bool vis[N][N];
- void dfs(int x,int y,int s){
- vis[x][y]=;
- Path t=pre[x][y][s];
- if(t.i==&&t.j==) return;
- dfs(t.i , t.j , t.s);
- if(t.i==x && t.j==y) dfs(t.i , t.j , s-t.s);
- }
- int main(){
- freopen("in","r",stdin);
- n=read();m=read();
- memset(f,0x3f,sizeof(f));
- for(int i=;i<=n;i++)
- for(int j=;j<=m;j++){
- a[i][j]=read();
- if(!a[i][j]) f[i][j][<<k]=,k++;
- }
- int All=<<k;
- for(int sa=;sa<All;sa++){
- for(int i=;i<=n;i++)
- for(int j=;j<=m;j++){
- for(int s=sa&(sa-);s;s=sa&(s-)){
- int _=f[i][j][s]+f[i][j][sa-s]-a[i][j];
- if(_<f[i][j][sa]){
- f[i][j][sa]=_;
- pre[i][j][sa]=Path(i,j,s);
- }
- }
- if(f[i][j][sa]<INF) q.push(MP(i,j)),inq[i][j]=;
- }
- spfa(sa);
- }
- int x=,y=,flag=;
- for(int i=;i<=n&&!flag;i++)
- for(int j=;j<=m;j++) if(!a[i][j]) {x=i;y=j;flag=;break;}
- dfs(x,y,All-);
- printf("%d\n",f[x][y][All-]);
- for(int i=;i<=n;i++){
- for(int j=;j<=m;j++){
- if(a[i][j]==) putchar('x');
- else if(vis[i][j]) putchar('o');
- else putchar('_');
- }
- puts("");
- }
- }
BZOJ 2595: [Wc2008]游览计划 [DP 状压 斯坦纳树 spfa]【学习笔记】的更多相关文章
- 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)
2595: [Wc2008]游览计划 Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1572 Solved: 7 ...
- [bzoj2595][WC2008]游览计划/[bzoj5180][Baltic2016]Cities_斯坦纳树
游览计划 bzoj-2595 wc-2008 题目大意:题目链接.题目连接. 注释:略. 想法:裸题求斯坦纳树. 斯坦纳树有两种转移方式,设$f[s][i]$表示联通状态为$s$,以$i$为根的最小代 ...
- BZOJ.2595.[WC2008]游览计划(DP 斯坦纳树)
题目链接 f[i][s]表示以i为根节点,当前关键点的连通状态为s(每个点是否已与i连通)时的最优解.i是枚举得到的根节点,有了根节点就容易DP了. 那么i为根节点时,其状态s的更新为 \(f[i][ ...
- bzoj:2595: [Wc2008]游览计划
Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点:否则表示控制该方块至少需要的志愿者数 ...
- bzoj 2595 [Wc2008]游览计划(斯坦纳树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2595 [题意] 给定N*M的长方形,选最少权值和的格子使得要求的K个点连通. [科普] ...
- BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树
[题目分析] 斯坦纳树=子集DP+SPFA? 用来学习斯坦纳树的模板. 大概就是用二进制来表示树包含的点,然后用跟几点表示树的形态. 更新分为两种,一种是合并两个子集,一种是换根,换根用SPFA迭代即 ...
- BZOJ2595 [Wc2008]游览计划 【状压dp + 最短路】
题目链接 BZOJ2595 题解 著名的斯坦纳树问题 设\(f[i][j][s]\)表示点\((i,j)\)与景点联通状况为\(s\)的最小志愿者数 设\(val[i][j]\)为\((i,j)\)需 ...
- 【BZOJ】2595: [Wc2008]游览计划
题意 \(n * m\)的网格,如果\(a_{i, j} = 0\)则表示景点,否则表示这里的需要的志愿者人数.求一种安排志愿者的方案使得所有景点连通且志愿者最少. 分析 本题可以插头dp,然而有一个 ...
- 【BZOJ2595】游览计划(状压DP,斯坦纳树)
题意:见题面(我发现自己真是越来越懒了) 有N*M的矩阵,每个格子有一个值a[i,j] 现要求将其中的K个点(称为关键点)用格子连接起来,取(i,j)的费用就是a[i,j] 求K点全部连通的最小花费以 ...
随机推荐
- 最小生成树—prim算法
最小生成树prim算法实现 所谓生成树,就是n个点之间连成n-1条边的图形.而最小生成树,就是权值(两点间直线的值)之和的最小值. 首先,要用二维数组记录点和权值.如上图所示无向图: int map[ ...
- 浅析@Deprecated,调用方法时出现横线划掉样式
Deprecated 这个注释是一个标记注释.所谓标记注释,就是在源程序中加入这个标记后,并不影响程序的编译,但有时编译器会显示一些警告信息. 那么Deprecated注释是什么意思呢?如果你经常使用 ...
- NYOJ 2356 哈希计划(模拟)
题目链接: http://acm.nyist.me/JudgeOnline/problem.php?id=2356 题目描述 众所周知,LLM的算法之所以菜,就是因为成天打游戏,最近LLM突然想玩&l ...
- screen乱码问题
在 .screenrc下设置: defencoding gbk encoding gbk gbk detatch+reattach后,设置失效,这时可以直接用命令来配置: ctrl+a :defenc ...
- 10年java过来人聊聊自己的自学、培训和工作经历
一 . 自我介绍 我叫王涛,我是一位北漂十年的码农,2008年9月份开始自学java,三个月后,自学无果,于2008年11月份开始参加培训,培训完之后,我觉得自己还是啥也不会,只会抄抄代码,竟然连de ...
- Flexbox学习总结
flex语法 采用Flex布局的元素,称为Flex容器(flex container),简称"容器".它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称& ...
- Java中泛型数组创建总结
在java中,可以声明一个泛型数组,不能通过直接通过T[] tarr=new T[10]的方式来创建数组,最简单的方式便是通过Array.newInstance(Classtype,int size) ...
- U盘安装CentOS 7问题解决
1 使用U盘安装最新版Centos时报错(CentOS-7-x86_64-DVD-1503-01): 错误提示:"Warning:could not boot;Warning: /dev/r ...
- 如何用docker部署redis cluster
前言 由于本人是个docker控,不喜欢安装各种环境,而且安装redis-trib也有点繁琐,索性用docker来做redis cluster. 本文用的是伪集群,真正的集群放到不同的机器即可.端口是 ...
- 一个滑动选中RecyclerView中Item的布局SlidingCheckLayout,手指滑过Item时多项选中。
SlidingCheckLayout是一个滑动选中RecyclerView中Item的布局,手指滑过Item时多项选中. 作者:竹尘居士 github:https://github.com/homgw ...