bzoj2595 [Wc2008]游览计划——斯坦纳树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595
今天刚学了斯坦纳树,还不太会,写一道题练习一下;
参考了博客:http://www.cnblogs.com/lazycal/archive/2013/08/31/bzoj-2595.html
代码也是模仿着写的,感觉有了更深的理解;
总之,大概就是两种转移方式,合并转移枚举子集即可,最短路转移用 spfa;
还要记录一个 pre 用来找到连通块内的点;
用哈希一样的方法把几个数 pack 起来的写法真神奇啊;
说实话还是有点云里雾里,不过成功写出了第一道斯坦纳树的题,感觉很好!
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int const maxn=,inf=0x3f3f3f3f;
int n,m,K,mx,f[maxn][maxn][<<maxn],a[maxn][maxn],pre[maxn][maxn][<<maxn];
int dx[]={,,-,},dy[]={,,,-};
bool vis[maxn][maxn],inq[maxn*maxn];
queue<int>q;
int pack(int i,int j){return i*+j;}
int pack2(int i,int j,int s){return i*+j*+s;}
void unpack(int x,int &i,int &j){i=x/; j=x%;}
void unpack2(int x,int &i,int &j,int &s){i=x/; j=(x/)%; s=x%;}
bool update(int x,int y,int s,int i,int j,int sta,int w)
{
if(f[x][y][s]>w){f[x][y][s]=w; pre[x][y][s]=pack2(i,j,sta); return ;}
return ;
}
void spfa(int sta)
{
while(q.size())
{
int i,j;
unpack(q.front(),i,j); inq[q.front()]=; q.pop();
for(int k=;k<;k++)
{
int x=i+dx[k],y=j+dy[k],tmp;
if(x==-||y==-||x==n||y==m)continue;//!!!
if(update(x,y,sta,i,j,sta,f[i][j][sta]+a[x][y])&&!inq[tmp=pack(x,y)])//不改变连通性
q.push(tmp),inq[tmp]=;
}
}
}
void dfs(int x,int y,int sta)
{
if(!pre[x][y][sta])return;
vis[x][y]=;
int i,j,s;
unpack2(pre[x][y][sta],i,j,s);
dfs(i,j,s);
if(i==x&&j==y)dfs(i,j,sta-s);//合并转移
}
void print()
{
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
if(!a[i][j])printf("x");
else if(vis[i][j])printf("o");
else printf("_");
}
printf("\n");
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(f,0x3f,sizeof f);
for(int i=;i<n;i++)
for(int j=;j<m;j++)
{
scanf("%d",&a[i][j]);
if(!a[i][j])f[i][j][<<(K++)]=;
}
mx=(<<K);
for(int sta=;sta<mx;sta++)
{
for(int i=;i<n;i++)
for(int j=,tmp;j<m;j++)//以(i,j)为媒介
{
for(int s=(sta&(sta-));s;s=(s-)&sta)
update(i,j,sta,i,j,s,f[i][j][s]+f[i][j][sta-s]-a[i][j]);//点权重复
if(f[i][j][sta]!=inf)q.push(tmp=pack(i,j)),inq[tmp]=;//inq!
}
spfa(sta);//更新不同位置的sta
}
for(int i=;i<n;i++)
for(int j=;j<m;j++)
if(!a[i][j])
{
printf("%d\n",f[i][j][mx-]);
dfs(i,j,mx-);
print();
return ;
}
}
bzoj2595 [Wc2008]游览计划——斯坦纳树的更多相关文章
- bzoj2595: [Wc2008]游览计划 斯坦纳树
斯坦纳树是在一个图中选取某些特定点使其联通(可以选取额外的点),要求花费最小,最小生成树是斯坦纳树的一种特殊情况 我们用dp[i][j]来表示以i为根,和j状态是否和i联通,那么有 转移方程: dp[ ...
- BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)
Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 2030 Solved: 986[Submit][Status][ ...
- 【BZOJ2595】[Wc2008]游览计划 斯坦纳树
[BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为 ...
- Luogu 4294 [WC2008]游览计划 | 斯坦纳树
题目链接 Luogu 4294 (我做这道题的时候BZOJ全站的SPJ都炸了 提交秒WA 幸好有洛谷) 题解 这道题是[斯坦纳树]的经典例题.斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个 ...
- 【BZOJ-2595】游览计划 斯坦纳树
2595: [Wc2008]游览计划 Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1518 Solved: 7 ...
- BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树
[题目分析] 斯坦纳树=子集DP+SPFA? 用来学习斯坦纳树的模板. 大概就是用二进制来表示树包含的点,然后用跟几点表示树的形态. 更新分为两种,一种是合并两个子集,一种是换根,换根用SPFA迭代即 ...
- P4294 [WC2008]游览计划 (斯坦纳树)
题目链接 差不多是斯坦纳树裸题,不过边权化成了点权,这样在合并两棵子树时需要去掉根结点的权值,防止重复. 题目还要求输出解,只要在转移时记录下路径,然后dfs一遍就好了. #include<bi ...
- 洛谷4294 [WC2008]游览计划——斯坦纳树
题目:https://www.luogu.org/problemnew/show/P4294 大概是状压.两种转移,一个是以同一个点为中心,S由自己的子集拼起来:一个是S相同.中心不同的同层转移. 注 ...
- BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*
BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...
随机推荐
- [Java]Java分层概念
service是业务层 action层即作为控制器 DAO (Data Access Object) 数据访问 1.JAVA中Action层, Service层 ,modle层 和 Dao层的功能 ...
- CSS——层级
层级问题:选中的盒子显示的效果并不完整,右边的边框并没有显示红色,原因是其右边的盒子压了它的边框. <!DOCTYPE html> <html lang="en" ...
- C#——接口的意义以及与抽象类的区别
接口的意义是什么呢?接口与抽象类又有什么区别?什么情况选择用接口?什么情况选择用抽象类? 接口的意义: 1.实际开发中的约束作用,继承接口的类必须实现接口规定的方法,方便多人开发中的协同,避免随意性. ...
- SQL基本操作——select into与临时表
SELECT INTO 语句从一个表中选取数据,然后把数据插入另一个表中,常用于创建表的备份复件或者用于对记录进行存档. --制作 "Persons" 表的备份复件: SELECT ...
- Escaping Closures 两点:本质是生命周期标示符
1.block需要(拷贝)保存: 2.block引用的环境变量需要处理. 相当于oc中的copy block. Escaping Closures A closure is said to escap ...
- centos7 安装zabbix3.4
1 打开yum安装rpm包,自动存放下载的rpm包 下次安装时,如果没有网可以自己制作yum源 打开文件 [root@localhost etc]# vim /etc/yum.conf keepcac ...
- cesium的学习
一.学习资料:http://cesiumjs.org/tutorials.html,看完6个教程后对图层加载.控件控制开关.地形数据叠加.模型添加.相机控制.图形绘制有一点了解.这也是cesium的主 ...
- 2018年为什么要学习Python?Python还有前景吗?
近年来,Python一直是当仁不让的开发入行首选,无论是职位数量.就业广度还是使用排行都远超其他语言,而且Python语言接近自然语言,学习起来非常的轻松简便,因此也越来越受到人们的欢迎.进入到201 ...
- 前端自动化构建工具gulp使用
1. 全局安装 gulp: $ npm install --global gulp 2. 作为项目的开发依赖(devDependencies)安装: $ npm install --save-dev ...
- node.js的初级使用
node.js的初级使用 作为一个全栈开发员怎么能不会node.js了?至少得会用node搭载环境吧!话不多说直接开干! 一.下载与安装: 官网:http://nodejs.cn/ 中文文档:http ...