题目: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]游览计划——斯坦纳树的更多相关文章

  1. bzoj2595: [Wc2008]游览计划 斯坦纳树

    斯坦纳树是在一个图中选取某些特定点使其联通(可以选取额外的点),要求花费最小,最小生成树是斯坦纳树的一种特殊情况 我们用dp[i][j]来表示以i为根,和j状态是否和i联通,那么有 转移方程: dp[ ...

  2. BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)

    Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 2030  Solved: 986[Submit][Status][ ...

  3. 【BZOJ2595】[Wc2008]游览计划 斯坦纳树

    [BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为 ...

  4. Luogu 4294 [WC2008]游览计划 | 斯坦纳树

    题目链接 Luogu 4294 (我做这道题的时候BZOJ全站的SPJ都炸了 提交秒WA 幸好有洛谷) 题解 这道题是[斯坦纳树]的经典例题.斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个 ...

  5. 【BZOJ-2595】游览计划 斯坦纳树

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

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

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

  7. P4294 [WC2008]游览计划 (斯坦纳树)

    题目链接 差不多是斯坦纳树裸题,不过边权化成了点权,这样在合并两棵子树时需要去掉根结点的权值,防止重复. 题目还要求输出解,只要在转移时记录下路径,然后dfs一遍就好了. #include<bi ...

  8. 洛谷4294 [WC2008]游览计划——斯坦纳树

    题目:https://www.luogu.org/problemnew/show/P4294 大概是状压.两种转移,一个是以同一个点为中心,S由自己的子集拼起来:一个是S相同.中心不同的同层转移. 注 ...

  9. BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*

    BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...

随机推荐

  1. 搜索条件两个时间,通过php数组排序,保证select语句between时间 前小后大

    //搜索条件两个时间,通过数组排序,保证select语句between时间 前小后大 $sort_array=[$_POST['clockDate1'],$_POST['clockDate2']]; ...

  2. JavaScript学习书签

    JavaScript常用正则表达式 闭包 JavaScipt DOM 变量提升

  3. linux设置crontab定时执行脚本备份mysql

    前言:mysqldump备份数据库命令 mysqldump -u root -psztx@2018 fengliuxiaosan > /dbbackup/fengliuxiaosan.sql## ...

  4. CAD向控件注册一个命令(com接口VB语言)

    主要用到函数说明: MxDrawXCustomFunction::Mx_RegistUserCustomCommand 向控件注册一个命令,用户在命令行输入命令名这个字符串,就会触发执行命令事件 命令 ...

  5. MySQL-----一对多

    一对多: 用户表和部门表 用户: 用户id 用户名 部门 1 George   1 2 Elizabeth 1 3 Bruce 2 4 Catherine 3 部门: 部门id 部门名称 1 CEO ...

  6. nagios新增监控集群、卸载监控集群批量操作

    1.一定要找应用侧确认每台节点上需要监控的进程,不要盲目以为所有hadoop集群的zk.journal啥的都一样,切记! 2.被监控节点只需要安装nagios-plugin和nrpe,依赖需要安装xi ...

  7. 【学QT】1 - QT的安装

    1.解压文件在/usr/local/下 #tar zxvf qt-x11-free-3.3.8b.tar.gz -C /usr/local 更改文件夹名称为qt #mv /usr/local/qt-x ...

  8. HBase(0.96)新的Java API操作

    package test; import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.ap ...

  9. 最短路径--Floyd算法

    Floyd算法 1.定义概览 Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被 ...

  10. 记一个简单的webpack.config.js

    module.exports = { entry: './basic/app.js', output: { path: './assets/', filename: '[name].bundle.js ...