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主要集合类的数据结构
1).ArrayList ArrayList维护着一个对象数组.如果调用new ArrayList()后,它会默认初始一个size=10的数组. 每次add操作都要检查数组容量,如果不够,重新 ...
- cocos creator游戏适配这事
在想cocos适配之前,我们想想网页是怎么适配的.浏览器有各种规格,网页的一般做法是:背景图片铺满,网页内容保持在背景图片上居中,就实现了适应或者适配.css一般这样: .bg{ height:582 ...
- Django - 一对多跨表操作
1.views.py 2.host.html 运行结果: 通过外键,来进行多表取值(多表取值包括后台取值及前端获取): 多表获取数据时,可以通过以下几种方式实现: 1.从query set 中获取某 ...
- Cookie, LocalStorage 与 SessionStorage说明
一.Cookie Cookie 大小限制为4KB左右,不适合大量数据的存储.因为它们由每个对服务器的请求来传递,这使得 cookie 速度很慢而且效率也不高.它的主要用途有保存登录信息,比如你 ...
- Huawei-R&S-网络工程师实验笔记20190525-设备登录、VRP基本配置、文件系统
>Huawei-R&S-网络工程师实验笔记20190525-设备登录.VRP基本配置.文件系统(环回接口.telnet远程.AAA登录.命令行.时钟.banner.文件目录) >& ...
- 【codeforces 510B】Fox And Two Dots
[题目链接]:http://codeforces.com/contest/510/problem/B [题意] 让你在一个二维的方格里面找环; 两个点有相邻的边它们才是相连的; 有环YES,没环NO ...
- (43). Spring Boot动态数据源(多数据源自动切换)【从零开始学Spring Boot】
在上一篇我们介绍了多数据源,但是我们会发现在实际中我们很少直接获取数据源对象进行操作,我们常用的是jdbcTemplate或者是jpa进行操作数据库.那么这一节我们将要介绍怎么进行多数据源动态切换.添 ...
- 洛谷 P2486 BZOJ 2243 [SDOI2011]染色
题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221” ...
- Java排序算法之冒泡、选择、插入、快速
JavaSort Java经典排序算法代码 2018-1-26更新:冒泡排序,选择排序,插入排序,快速排序 1. 冒泡排序 特点:效率低,实现简单 思想(从小到大排): 第1个数和第2个数比较,如果第 ...
- PHP中echo和print的区别
这篇文章主要介绍了PHP中echo和print的区别,针对二者使用中常见的用法区别进行了较为深入的总结与分析,需要的朋友可以参考下 一般来说,PHP中动态输出HTML内容,是通过print 和 ech ...