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, 则该方块为一个 ...
随机推荐
- python调用java API
JPype documentation JPype is an effort to allow python programs full access to java class libraries. ...
- 微信小程序php后台实现
这里简单介绍用php后台实现获取openid并保存到数据库: 微信的登陆流程是这样的 首先前端发送请求到服务器: wx.login({ success: function (res) { var co ...
- POJ 3070 - 快速矩阵幂求斐波纳契数列
这题并不复杂. 设$A=\begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix}$ 由题中公式: $\begin{pmatrix}f(n+1) & ...
- (转)Hibernate中的多表操作
http://blog.csdn.net/yerenyuan_pku/article/details/70556208 Hibernate中的多表操作 在实际开发中,我们不可能只是简简单单地去操作单表 ...
- 人工智能时代,你为什么一定要学Python?
Python岗位年薪至少在10-20w之间,而且除了北.上.广.深外,杭州和合肥等二.三线城市的待遇正在与一线城市持平.未来,无论你身处何地,都能享受到人工智能.Python“带来的“市场红利”. P ...
- 跳转语句(break、continue)
break语句 在switch条件语句和循环语句中都可以使用break语句.当它出现在switch条件语句中时,作用是终止某个case并跳出switch结构. 当它出现在循环语句中,作用是跳出循环语句 ...
- SqlServer 【基 本 操 作】
1.Row_Number() select * from (select Row_Number() over (order by FSalary) as 'RowNum' ,* from dbo.T_ ...
- list.h在用户态下的应用
一.背景 list.h文件位于linux/include下,内核中链表的操作函数都在其中.它有许多关于链表的操作函数,所以我们可以尝试将list.h拉到用户态中来使用,这样,我们在用户态中若要用到链表 ...
- Keil MDK下如何设置非零初始化变量(复位后变量值不丢失)
一些工控产品,当系统复位后(非上电复位),可能要求保持住复位前RAM中的数据,用来快速恢复现场,或者不至于因瞬间复位而重启现场设备.而keil mdk在默认情况下,任何形式的复位都会将RAM区的非初始 ...
- Awesome Python(中文对照)
python中文资源大全:https://github.com/jobbole/awesome-python-cn A curated list of awesome Python framework ...