传送门

题意:略


论文 《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]【学习笔记】的更多相关文章

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

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

  2. [bzoj2595][WC2008]游览计划/[bzoj5180][Baltic2016]Cities_斯坦纳树

    游览计划 bzoj-2595 wc-2008 题目大意:题目链接.题目连接. 注释:略. 想法:裸题求斯坦纳树. 斯坦纳树有两种转移方式,设$f[s][i]$表示联通状态为$s$,以$i$为根的最小代 ...

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

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

  4. bzoj:2595: [Wc2008]游览计划

    Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点:否则表示控制该方块至少需要的志愿者数 ...

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

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

  6. BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树

    [题目分析] 斯坦纳树=子集DP+SPFA? 用来学习斯坦纳树的模板. 大概就是用二进制来表示树包含的点,然后用跟几点表示树的形态. 更新分为两种,一种是合并两个子集,一种是换根,换根用SPFA迭代即 ...

  7. BZOJ2595 [Wc2008]游览计划 【状压dp + 最短路】

    题目链接 BZOJ2595 题解 著名的斯坦纳树问题 设\(f[i][j][s]\)表示点\((i,j)\)与景点联通状况为\(s\)的最小志愿者数 设\(val[i][j]\)为\((i,j)\)需 ...

  8. 【BZOJ】2595: [Wc2008]游览计划

    题意 \(n * m\)的网格,如果\(a_{i, j} = 0\)则表示景点,否则表示这里的需要的志愿者人数.求一种安排志愿者的方案使得所有景点连通且志愿者最少. 分析 本题可以插头dp,然而有一个 ...

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

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

随机推荐

  1. Frame Stacking(拓扑排序)

    题目链接:http://acm.tju.edu.cn/toj/showp1076.html1076.   Frame Stacking Time Limit: 1.0 Seconds   Memory ...

  2. UnityShader 表面着色器简单例程集合

    0.前言 这些简单的shader程序都是写于2015年的暑假.当时实验室空调坏了,30多个人在实验室中挥汗如雨,闷热中学习shader的日子还历历在目.这些文章闲置在我个人博客中,一年将过,师弟也到了 ...

  3. Xtrabackup实现数据的备份与恢复

    Xtrabackup介绍 Xtrabackup是由percona开源的免费数据库热备份软件,它能对InnoDB数据库和XtraDB存储引擎的数据库非阻塞地备份(对于MyISAM的备份同样需要加表锁): ...

  4. Vuex初识

    vuex是vue中单向数据流的一个状态管理模式,它可以集中存储管理应用中所有组件的状态,并且有一套相应的规则可以去预测数据的变化.类似与此的还有react中的redux,dva等状态管理模式. 一般我 ...

  5. MLlib--SVD算法

    转载请标明出处http://www.cnblogs.com/haozhengfei/p/4db529fa9f4c042673c6dc8218251f6c.html SVD算法 1.1什么是SVD?   ...

  6. C#面试常见题目

    1.CTS.CLS.CLR分别作何解释 CTS:Common Type System 通用系统类型.Int32.Int16→int.String→string.Boolean→bool CLS:Com ...

  7. VIM命令模式与输入模式切换

     vi编辑器 vi是UNIX和类UNIX环境下的可用于创建文件的屏幕编辑器.vi有两种工作模式:命令模式和文本输入模式.启动vi需要输入vi,按[Spacebar]键并输入文件名后回车. 切换模式键 ...

  8. Python实现简易Web服务器

     1.请自行了解HTTP协议 http://www.cnblogs.com/reboot51/p/8358129.html(点击跳转) 2.创建Socket服务,监听指定IP和端口 3.以阻塞方式等待 ...

  9. Java数据持久层框架 MyBatis之API学习三(XML 映射配置文件)

    对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...

  10. ASP.NET MVC5 中百度ueditor富文本编辑器的使用

    随着网站信息发布内容越来越多,越来越重视美观,富文本编辑就是不可缺少的了,众多编辑器比较后我选了百度的ueditor富文本编辑器. 百度ueditor富文本编辑器分为两种一种是完全版的ueditor, ...