[bzoj2595][WC2008]游览计划/[bzoj5180][Baltic2016]Cities_斯坦纳树
游览计划 bzoj-2595 wc-2008
注释:略。
想法:裸题求斯坦纳树。
斯坦纳树有两种转移方式,设$f[s][i]$表示联通状态为$s$,以$i$为根的最小代价。
第一个转移就是$f[s][i]=f[t][i]+f[s-t][i]$。这个显然但是是针对边权的,这个题我们需要减掉多算的点权更新答案。
第二个转移是相同的$s$,即$f[s][i]=f[s][j]+E[i][j]$。
发现很像三角形不等式,用$spfa$转移即可。
代码2595:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define inf 1e9
#define N 11
#define M 1050
using namespace std;
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0,f=1; char c=nc(); while(c<48) {if(c=='-') f=-1; c=nc();} while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*f;}
struct Node {int x,y,S;}pre[N][N][M];
struct par {int x,y;};
int a[N][N],f[N][N][M];
int n,m,tot=0;
int dic_x[]={0,0,1,-1};
int dic_y[]={1,-1,0,0};
bool vis[N][N];
queue<par>q;
void spfa(int cur)
{
while(!q.empty())
{
par p=q.front(); q.pop();
vis[p.x][p.y]=false;
for(int k=0;k<4;k++)
{
int wx=p.x+dic_x[k],wy=p.y+dic_y[k];
if(wx<1||wx>n||wy<1||wy>m) continue;
if(f[wx][wy][cur]>f[p.x][p.y][cur]+a[wx][wy])
{
f[wx][wy][cur]=f[p.x][p.y][cur]+a[wx][wy];
pre[wx][wy][cur]=(Node){p.x,p.y,cur};
if(!vis[wx][wy]) vis[wx][wy]=true,q.push((par){wx,wy});
}
}
}
}
void dfs(int x,int y,int now)
{
// printf("%d %d %d\n",x,y,now);
vis[x][y]=1;
// printf("%d %d %d\n",x,y,now);
Node tmp=pre[x][y][now];
// printf("%d %d %d\n",x,y,now);
if(!tmp.x&&!tmp.y) return;
// printf("%d %d %d\n",x,y,now);
dfs(tmp.x,tmp.y,tmp.S);
// printf("%d %d %d\n",x,y,now);
if(tmp.x==x&&tmp.y==y) dfs(tmp.x,tmp.y,now-tmp.S);
// printf("%d %d %d\n",x,y,now);
}
int main()
{
n=rd(),m=rd();
memset(f,0x3f,sizeof f);
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
{
a[i][j]=rd();
if(!a[i][j]) f[i][j][1<<tot]=0,tot++;
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++) printf("%d ",a[i][j]);
// puts("");
// }
// cout << tot << endl ;
int all=(1<<tot)-1;
for(int sta=0;sta<=all;sta++)
{
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
{
for(int s=sta;s;s=(s-1)&sta)
{
if(f[i][j][s]+f[i][j][sta-s]-a[i][j]<f[i][j][sta])
{
f[i][j][sta]=f[i][j][s]+f[i][j][sta-s]-a[i][j];
pre[i][j][sta]=(Node){i,j,s};
}
}
if(f[i][j][sta]<inf) q.push((par){i,j}),vis[i][j]=true;
// printf("%d\n",f[i][j][sta]);
}
spfa(sta);
}
int ansx,ansy; bool flag=false;
for(int i=1;i<=n&&!flag;i++) for(int j=1;j<=m;j++) if(!a[i][j]) {ansx=i,ansy=j,flag=true; break;}
cout << f[ansx][ansy][all] << endl ;
memset(vis,false,sizeof vis);
dfs(ansx,ansy,all);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(!a[i][j]) putchar('x');
else if(vis[i][j]) putchar('o');
else putchar('_');
}
puts("");
}
return 0;
}
代码5180:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 100010
#define M 200010
using namespace std; typedef long long ll;
priority_queue<pair<ll,int> >q;
int head[N],to[M<<1],nxt[M<<1],tot; ll val[M<<1];
ll f[50][N];
bool vis[50][N];
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0,f=1; char c=nc(); while(c<48) {if(c=='-') f=-1; c=nc();} while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*f;}
inline void add(int x,int y,ll z) {to[++tot]=y; val[tot]=z; nxt[tot]=head[x]; head[x]=tot;}
int main()
{
memset(f,0x3f,sizeof f);
int n=rd(),k=rd(),m=rd();
for(int i=1;i<=k;i++) {int x=rd(); f[1<<(i-1)][x]=0;}
for(int i=1;i<=m;i++) {int x=rd(),y=rd(); ll z=rd(); add(x,y,z),add(y,x,z);}
int all=(1<<k)-1;
for(int i=1;i<=all;i++)
{
for(int j=i;j;j=(j-1)&i)
{
for(int l=1;l<=n;l++)
{
f[i][l]=min(f[i][l],f[j][l]+f[i-j][l]);
}
}
for(int j=1;j<=n;j++) q.push(make_pair(-f[i][j],j));
while(!q.empty())
{
int x=q.top().second; q.pop();
if(vis[i][x]) continue;
vis[i][x]=true;
for(int j=head[x];j;j=nxt[j]) if(f[i][to[j]]>f[i][x]+val[j])
{
f[i][to[j]]=f[i][x]+val[j];
q.push(make_pair(-f[i][to[j]],to[j]));
}
}
}
ll ans=0x3f3f3f3f3f3f3f3f;
for(int i=1;i<=n;i++) ans=min(ans,f[all][i]);
cout << ans << endl ;
return 0;
}
小结:斯坦纳树类似组合最优化问题,想法非常优秀。
[bzoj2595][WC2008]游览计划/[bzoj5180][Baltic2016]Cities_斯坦纳树的更多相关文章
- BZOJ 2595: [Wc2008]游览计划 [DP 状压 斯坦纳树 spfa]【学习笔记】
传送门 题意:略 论文 <SPFA算法的优化及应用> http://www.cnblogs.com/lazycal/p/bzoj-2595.html 本题的核心就是求斯坦纳树: Stein ...
- luogu4294 [WC2008]游览计划(状压DP/斯坦纳树)
link 题目大意:给定一个网格图,有些点是关键点,选择格点有代价,求把所有关键点联通的最小代价 斯坦纳树模板题 斯坦纳树问题:给定一个图结构,有一些点是关键点,求把这些关键点联通的最小代价e 斯坦纳 ...
- BZOJ_5180_[Baltic2016]Cities_ 斯坦纳树
BZOJ_5180_[Baltic2016]Cities_ 斯坦纳树 题意: 给定n个点,m条双向边的图.其中有k个点是重要的.每条边都有一定的长度. 现在要你选定一些边来构成一个图,要使得k个重要的 ...
- BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*
BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...
- BZOJ2595 WC2008游览计划(斯坦纳树)
斯坦纳树板子题. 考虑状压dp,设f[i][j][S]表示当前在点(i,j)考虑转移,其所在的联通块包含的关键点集(至少)为S的答案. 转移时首先枚举子集,有f[i][j][S]=min{f[i][j ...
- bzoj2595 [Wc2008]游览计划——斯坦纳树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595 今天刚学了斯坦纳树,还不太会,写一道题练习一下: 参考了博客:http://www.c ...
- 斯坦纳树 [bzoj2595][wc2008]游览计划 题解
话说挺早就写过斯坦纳树了,不过当时没怎么总结,也不是很理解……现在来个小结吧~ 斯坦纳树就是包含给定点的最小生成树(个人理解权值应当为正). 一般来讲,给定点的数目应该很小吧...于是我们可以用状压D ...
- 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][ ...
随机推荐
- web页面调用IOS的事件
/** * js 调用ios的方法 * @param callback */ function connectWebViewJavascriptBridge(callback) { if (windo ...
- 11G RAC环境数据库启动和关闭
一步启动Oracle (1) 启动整个集群 # ./crsctl start cluster -all -all选项启动整个集群. 不加-all选项只能启动本节点的服务. (2) 启动本节点集群 以下 ...
- iview modal 点击打开窗口,打开前先销毁里面的内容再打开
<Modal v-model="addSubOrgModal" @on-cancel="addSubOrgCancel" @on-visible-chan ...
- Linux 编译升级 FFmpeg 步骤
如果服务器已经安装了一个 Ffmpeg 的话,比如已安装在 /usr/local/ffmpeg 目录.Linux下版本升级步骤如下: 1.下载 ffmpeg-*.tar.gz到 Ffmpeg 官网 h ...
- CPP-基础:文字常量区
内存不可写 char* 先看一个例子 ///////////// //代码1 #include <string> main() { char *buf = "good morni ...
- Mysql 访问远程数据库,报错:1130-host ... is not allowed to connect to this MySql server 开放mysql远程连接 不使用localhost
参考:http://www.cnblogs.com/xyzdw/archive/2011/08/11/2135227.html 解决方法: 1. 改表法. 可能是你的帐号不允许从远程登陆,只能在loc ...
- 最短路 || POJ 1847 Tram
POJ 1847 最短路 每个点都有初始指向,问从起点到终点最少要改变多少次点的指向 *初始指向的那条边长度为0,其他的长度为1,表示要改变一次指向,然后最短路 =========高亮!!!===== ...
- centOS出现 -bash: vim: command not found
问题描述 用centos 的主机的時候, 用 vim 时出现 -bash: vim: command not found. 只能使用 vi. 那么如何安裝 vim 呢? 解决步骤 1.查看是否安装 输 ...
- VIO第二讲_allen方差工具
1,首先,安装ceres依赖项,见高博14讲116页,然后下载编译安装ceres: git clone https://github.com/ceres-solver/ceres-solver cd ...
- 《3+1团队》【Alpha】Scrum meeting 1
项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 3+1团队 团队博客地址 https://home.cnblogs.com/u/3-1group ...