题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595

今天刚学了斯坦纳树,还不太会,写一道题练习一下;

参考了博客:http://www.cnblogs.com/lazycal/archive/2013/08/31/bzoj-2595.html

代码也是模仿着写的,感觉有了更深的理解;

总之,大概就是两种转移方式,合并转移枚举子集即可,最短路转移用 spfa;

还要记录一个 pre 用来找到连通块内的点;

用哈希一样的方法把几个数 pack 起来的写法真神奇啊;

说实话还是有点云里雾里,不过成功写出了第一道斯坦纳树的题,感觉很好!

代码如下:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<queue>
  5. using namespace std;
  6. int const maxn=,inf=0x3f3f3f3f;
  7. int n,m,K,mx,f[maxn][maxn][<<maxn],a[maxn][maxn],pre[maxn][maxn][<<maxn];
  8. int dx[]={,,-,},dy[]={,,,-};
  9. bool vis[maxn][maxn],inq[maxn*maxn];
  10. queue<int>q;
  11. int pack(int i,int j){return i*+j;}
  12. int pack2(int i,int j,int s){return i*+j*+s;}
  13. void unpack(int x,int &i,int &j){i=x/; j=x%;}
  14. void unpack2(int x,int &i,int &j,int &s){i=x/; j=(x/)%; s=x%;}
  15. bool update(int x,int y,int s,int i,int j,int sta,int w)
  16. {
  17. if(f[x][y][s]>w){f[x][y][s]=w; pre[x][y][s]=pack2(i,j,sta); return ;}
  18. return ;
  19. }
  20. void spfa(int sta)
  21. {
  22. while(q.size())
  23. {
  24. int i,j;
  25. unpack(q.front(),i,j); inq[q.front()]=; q.pop();
  26. for(int k=;k<;k++)
  27. {
  28. int x=i+dx[k],y=j+dy[k],tmp;
  29. if(x==-||y==-||x==n||y==m)continue;//!!!
  30. if(update(x,y,sta,i,j,sta,f[i][j][sta]+a[x][y])&&!inq[tmp=pack(x,y)])//不改变连通性
  31. q.push(tmp),inq[tmp]=;
  32. }
  33. }
  34. }
  35. void dfs(int x,int y,int sta)
  36. {
  37. if(!pre[x][y][sta])return;
  38. vis[x][y]=;
  39. int i,j,s;
  40. unpack2(pre[x][y][sta],i,j,s);
  41. dfs(i,j,s);
  42. if(i==x&&j==y)dfs(i,j,sta-s);//合并转移
  43. }
  44. void print()
  45. {
  46. for(int i=;i<n;i++)
  47. {
  48. for(int j=;j<m;j++)
  49. {
  50. if(!a[i][j])printf("x");
  51. else if(vis[i][j])printf("o");
  52. else printf("_");
  53. }
  54. printf("\n");
  55. }
  56. }
  57. int main()
  58. {
  59. scanf("%d%d",&n,&m);
  60. memset(f,0x3f,sizeof f);
  61. for(int i=;i<n;i++)
  62. for(int j=;j<m;j++)
  63. {
  64. scanf("%d",&a[i][j]);
  65. if(!a[i][j])f[i][j][<<(K++)]=;
  66. }
  67. mx=(<<K);
  68. for(int sta=;sta<mx;sta++)
  69. {
  70. for(int i=;i<n;i++)
  71. for(int j=,tmp;j<m;j++)//以(i,j)为媒介
  72. {
  73. for(int s=(sta&(sta-));s;s=(s-)&sta)
  74. update(i,j,sta,i,j,s,f[i][j][s]+f[i][j][sta-s]-a[i][j]);//点权重复
  75. if(f[i][j][sta]!=inf)q.push(tmp=pack(i,j)),inq[tmp]=;//inq!
  76. }
  77. spfa(sta);//更新不同位置的sta
  78. }
  79. for(int i=;i<n;i++)
  80. for(int j=;j<m;j++)
  81. if(!a[i][j])
  82. {
  83. printf("%d\n",f[i][j][mx-]);
  84. dfs(i,j,mx-);
  85. print();
  86. return ;
  87. }
  88. }

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. 实例分割:MaskXRCnn 与Visual Genome数据集

    一.VG数据集 机器学习领域的突破突然让计算机获得了以未曾有的高精度识别图像中物体的能力--几乎达到了让人惊恐的程度.现在的问题是机器是否还能更上层楼,学会理解这些图片中所发生的事件. Visual ...

  2. Redis 之sentinel运维监控

    有三台redis服务器6379.6380.6381,配置6379为主服务器,6380与6381都为6379的从服务器.如果主服务器6379挂掉了,我们怎么办? 方式一:手动修改从服务器的配置,将638 ...

  3. 用jquery-easyui的布局layout写后台管理页面

    先在官网下载easyui文档 引入头部文件 <link rel="stylesheet" type="text/css" href="${pag ...

  4. kesci---2019大数据挑战赛预选赛---情感分析

    一.预选赛题------文本情感分类模型 本预选赛要求选手建立文本情感分类模型,选手用训练好的模型对测试集中的文本情感进行预测,判断其情感为「Negative」或者「Positive」.所提交的结果按 ...

  5. 30.3 FCL中的混合构造

     30.3.2 Monitor类和同步块 internal sealed class Transaction { private readonly object _lock = new object( ...

  6. Linux内核源码特殊用法

    崇拜并且转载的: http://ilinuxkernel.com/files/5/Linux_Kernel_Source_Code.htm Linux内核源码特殊用法 1 前言 Linux内核源码主要 ...

  7. Mysql 模糊查询总结

    语法: SELECT 字段集 FROM 表名 WHERE 字段名 LIKE 条件 模糊查询有四种匹配模式: 1.%:匹配任意0个或多个字符. 2._:匹配任意1个字符. 3.[]:匹配括号内所列字符中 ...

  8. APK动态加载框架 https://github.com/singwhatiwanna/dynamic-load-apk

    https://github.com/singwhatiwanna/dynamic-load-apk

  9. hdu2009 求数列的和【C++】

    求数列的和 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  10. SSL常用专业缩略语汇总

    JKS - Java KeyStore JAVA密钥库 OCSP - Online Certificate Status Protocol证书在线状态协议. SAN - Subject Alterna ...