P4294 [WC2008]游览计划 (斯坦纳树)
差不多是斯坦纳树裸题,不过边权化成了点权,这样在合并两棵子树时需要去掉根结点的权值,防止重复。
题目还要求输出解,只要在转移时记录下路径,然后dfs一遍就好了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=+,inf=0x3f3f3f3f;
const int dx[]= {,,-,};
const int dy[]= {-,,,};
int n,m,k,dp[<<][N][N],a[N][N],inq[N][N];
char s[N][N];
struct D {int x,y;} X[N];
struct Ans {int S,x,y;} ansS,nxt[<<][N][N];
queue<D> q;
void upd(int x,int y,int c,int S,int x2,int y2) {
if(dp[S][x][y]>c) {
dp[S][x][y]=c;
nxt[S][x][y]= {S,x2,y2};
if(!inq[x][y])inq[x][y]=,q.push({x,y});
}
}
void spfa(int S) {
while(q.size())q.pop();
memset(inq,,sizeof inq);
for(int i=; i<=n; ++i)
for(int j=; j<=m; ++j)
if(dp[S][i][j]!=inf)inq[i][j]=,q.push({i,j});
while(q.size()) {
int x=q.front().x,y=q.front().y;
q.pop(),inq[x][y]=;
for(int i=; i<; ++i) {
int x2=x+dx[i],y2=y+dy[i];
if(x2<||x2>n||y2<||y2>m)continue;
upd(x2,y2,dp[S][x][y]+a[x2][y2],S,x,y);
}
}
}
void dfs(int S,int x,int y) {
if(!a[x][y])s[x][y]='x';
else s[x][y]='o';
int S2=nxt[S][x][y].S,x2=nxt[S][x][y].x,y2=nxt[S][x][y].y;
if(!S2)return;
else if(S2==S)dfs(S2,x2,y2);
else dfs(S2,x2,y2),dfs(S^S2,x2,y2);
}
int main() {
scanf("%d%d",&n,&m);
for(int i=; i<=n; ++i)
for(int j=; j<=m; ++j) {
scanf("%d",&a[i][j]);
if(!a[i][j])X[k++]= {i,j};
}
memset(dp,inf,sizeof dp);
for(int i=; i<k; ++i)dp[<<i][X[i].x][X[i].y]=a[X[i].x][X[i].y];
for(int S=; S<(<<k); ++S) {
for(int S2=(S-)&S; S2; S2=(S2-)&S)
for(int i=; i<=n; ++i)
for(int j=; j<=m; ++j) {
dp[S][i][j]=min(dp[S][i][j],dp[S2][i][j]+dp[S^S2][i][j]-a[i][j]);
if(dp[S][i][j]==dp[S2][i][j]+dp[S^S2][i][j]-a[i][j])nxt[S][i][j]= {S2,i,j};
}
spfa(S);
}
int ans=inf;
for(int i=; i<=n; ++i)
for(int j=; j<=m; ++j) {
ans=min(ans,dp[(<<k)-][i][j]);
if(ans==dp[(<<k)-][i][j])ansS= {(<<k)-,i,j};
}
for(int i=; i<=n; ++i)
for(int j=; j<=m; ++j)s[i][j]='_';
dfs(ansS.S,ansS.x,ansS.y);
printf("%d\n",ans);
for(int i=; i<=n; ++i) {
for(int j=; j<=m; ++j)putchar(s[i][j]);
puts("");
}
return ;
}
P4294 [WC2008]游览计划 (斯坦纳树)的更多相关文章
- 【BZOJ2595】[Wc2008]游览计划 斯坦纳树
[BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为 ...
- Luogu 4294 [WC2008]游览计划 | 斯坦纳树
题目链接 Luogu 4294 (我做这道题的时候BZOJ全站的SPJ都炸了 提交秒WA 幸好有洛谷) 题解 这道题是[斯坦纳树]的经典例题.斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个 ...
- 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][ ...
- BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树
[题目分析] 斯坦纳树=子集DP+SPFA? 用来学习斯坦纳树的模板. 大概就是用二进制来表示树包含的点,然后用跟几点表示树的形态. 更新分为两种,一种是合并两个子集,一种是换根,换根用SPFA迭代即 ...
- bzoj2595 [Wc2008]游览计划——斯坦纳树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595 今天刚学了斯坦纳树,还不太会,写一道题练习一下: 参考了博客:http://www.c ...
- 洛谷4294 [WC2008]游览计划——斯坦纳树
题目:https://www.luogu.org/problemnew/show/P4294 大概是状压.两种转移,一个是以同一个点为中心,S由自己的子集拼起来:一个是S相同.中心不同的同层转移. 注 ...
- 【BZOJ-2595】游览计划 斯坦纳树
2595: [Wc2008]游览计划 Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1518 Solved: 7 ...
- bzoj2595 / P4294 [WC2008]游览计划
P4294 [WC2008]游览计划 斯坦纳树 斯坦纳树,是一种神奇的树.它支持在一个连通图上求包含若干个选定点的最小生成树. 前置算法:spfa+状压dp+dfs(大雾) 我们设$f[o][P]$为 ...
随机推荐
- C学习笔记-字符串的格式化输出和输入
存储方式 字符串是内存中一段连续的char空间,以'\0'结尾 字符串就是0结尾的连续char的内存 '\0' <=> 0 <=> null printf函数,putchar函 ...
- 如何写出优雅耐看的JavaScript代码
参考链接:https://segmentfault.com/a/1190000020444918?utm_medium=hao.caibaojian.com&utm_source=hao.ca ...
- python数值列表
使用range函数生成数值列表 使用range函数打印1~5的数字 for i in range(1,6): print(i) 输出 1 2 3 4 5 利用range函数生成数值列表 >> ...
- iis实现方向代理
将请求的网址重写重定向到其它网址.当80端口被占用无法同时使用两个Web服务的解决方案,使得IIS和Apache Tomcat 共存 0|1环境 WindowServer 2008 IIS7 Apac ...
- shell 字符
Shell 中的符号: 在shell中有很多符号代表了一些意思,重点说说 键盘上的符号在shell中的意义. 通配符: ~ 匹配家目录 ? 匹配单个字符.( ?之匹配单一的一个字符.x11 这种的就 ...
- SQL Server 2019 Linux Docker 在主机上以其他非根用户的身份运行容器
docker logs mssql2019SQL Server 2019 will run as non-root by default.This container is running as us ...
- BEGIN_MESSAGE_MAP和END_MESSAGE_MAP()
这两个宏表示这个类的消息映射开始和结束,中间的宏定义定义了此类的所有的消息映射.前面的afx_msg void OnPaint():只是声明OnPaint()函数的一个消息处理函数,然后是OnPain ...
- Points Division(线段树+DP)2019牛客暑期多校训练营(第一场)
题意:https://ac.nowcoder.com/acm/contest/881/I 给你n个平面上的点,每个点有a.b两个权值,现在让你划分成两个区域(要求所有A集合里的点不能在任何B集合里的点 ...
- Springboot使用javaMail进行邮件发送
导入相关依赖 <!--邮件发送--> <dependency> <groupId>javax.mail</groupId> <artifactId ...
- JS基础_对象的简介、对象的基本操作
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...