题解:

$k<=20,$ 考虑状压dp.
从 $1$ 号点走到 $n$ 号点经过的点的个数可能会非常多,但是强制要求经过的点一共才 $20$ 个.
而我们发现这个题好就好在可以经过某个城市,而不停留.
故我们在关键点之间进行转移的时候可以直接走最短路,而不用管别的.
令方程 $f[i][j]$ 表示访问过的关键点集合为 $i,$ 当前在点 $i$ 的最短路径.
考虑转移:
枚举下一个可以到达的关键节点 $k,$ 能转移到 $k$ 的条件是 $i$ 中有 $k$ 需要提前访问的元素,这个可以提前预处理.
如果成功转移,则方程为 $f[i|(1<<k)][i]+d[j][k],$ 其中 $d[j][k]$ 表示 $j$ 到 $k$ 的最短路.
由于 $j$ 只可能取到 $[1,20],$ 所以只需暴力跑 $20$ 遍最短路即可.

我不会说我还没调过样例~

以后有时间的话再调吧~

Code:

  1. #include <bits/stdc++.h>
  2. #define N 20003
  3. #define ll long long
  4. #define inf 1000000000
  5. #define M (1<<21)
  6. #define setIO(s) freopen(s".in","r",stdin)
  7. using namespace std;
  8. ll d[30][N],f[M][22];
  9. int n,m,K,edges;
  10. int done[N],hd[N],to[N<<1],nex[N<<1],val[N<<1],Log[22],phase[22];
  11. int count(int c)
  12. {
  13. int l=0;
  14. for(;c;c>>=1) if(c&1) ++l;
  15. return l;
  16. }
  17. void getmin(ll &a,ll b)
  18. {
  19. if(b<a) a=b;
  20. }
  21. void addedge(int u,int v,int c)
  22. {
  23. nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;
  24. }
  25. struct Node
  26. {
  27. int u;
  28. ll dis;
  29. Node(int u=0,ll dis=0):u(u),dis(dis){}
  30. bool operator<(Node b)const
  31. {
  32. return b.dis<dis;
  33. }
  34. };
  35. priority_queue<Node>q;
  36. void Dijkstra(int s)
  37. {
  38. int i,v,u;
  39. for(i=0;i<=n;++i) d[s][i]=inf,done[i]=0;
  40. for(d[s][s]=0,q.push(Node(s,0));!q.empty();)
  41. {
  42. Node e=q.top(); q.pop();
  43. u=e.u;
  44. if(done[u]) continue;
  45. done[u]=1;
  46. for(i=hd[u];i;i=nex[i])
  47. {
  48. v=to[i];
  49. if(d[s][v]>d[s][u]+val[i])
  50. {
  51. d[s][v]=d[s][u]+val[i];
  52. q.push(Node(v,d[s][v]));
  53. }
  54. }
  55. }
  56. }
  57. int main()
  58. {
  59. int i,j;
  60. setIO("input");
  61. scanf("%d%d%d",&n,&m,&K);
  62. for(i=0;i<=20;++i) Log[i]=(1<<i);
  63. for(i=1;i<=m;++i)
  64. {
  65. int a,b,c;
  66. scanf("%d%d%d",&a,&b,&c),addedge(a,b,c),addedge(b,a,c);
  67. }
  68. for(i=1;i<=K+1;++i) Dijkstra(i);
  69. if(!K)
  70. {
  71. printf("%lld\n",d[1][n]);
  72. return 0;
  73. }
  74. int Q;
  75. scanf("%d",&Q);
  76. for(i=1;i<=Q;++i)
  77. {
  78. int a,b;
  79. scanf("%d%d",&a,&b);
  80. if(a!=1) phase[b]+=Log[a-2];
  81. }
  82. memset(f,0x3f,sizeof(f));
  83. for(int sta=1;sta<Log[K];++sta)
  84. {
  85. if(count(sta)==1)
  86. {
  87. for(j=2;j<=K+1;++j)
  88. {
  89. if(Log[j-2]&sta)
  90. {
  91. f[sta][j-2]=d[1][j];
  92. printf("%d %lld\n",j,f[sta][j-2]);
  93. break;
  94. }
  95. }
  96. }
  97. for(j=2;j<=K+1;++j)
  98. {
  99. if(Log[j-2]&sta)
  100. {
  101. for(int cc=2;cc<=K+1;++cc)
  102. {
  103. if( !(Log[cc-2]&sta) && ((sta & phase[cc]) == phase[cc]) )
  104. getmin(f[sta|Log[cc-2]][cc-2],f[sta][j-2]+d[j][cc]);
  105. }
  106. }
  107. }
  108. }
  109. ll ans=10000000000;
  110. for(i=2;i<=K+1;++i)
  111. {
  112. getmin(ans, f[Log[K]-1][i-2]+d[i][n]);
  113. }
  114. printf("%lld\n",ans);
  115. return 0;
  116. }

  

BZOJ 1097: [POI2007]旅游景点atr 状态压缩+Dijkstra的更多相关文章

  1. BZOJ 1097: [POI2007]旅游景点atr( 最短路 + 状压dp )

    先最短路预处理, 然后状压就行了 -------------------------------------------------------------------------- #include ...

  2. bzoj [POI2007]旅游景点atr 状态压缩+Dij

    [POI2007]旅游景点atr Time Limit: 30 Sec  Memory Limit: 357 MBSubmit: 2258  Solved: 595[Submit][Status][D ...

  3. bzoj 1097 [POI2007]旅游景点atr(最短路,状压DP)

    [题意] 给定一个n点m边的无向图,要求1开始n结束而且顺序经过k个点,给出经过关系x,y代表y必须在x之后经过,求最短路. [思路] 先对k个点进行spfa求出最短路. 设f[s][i]代表经过点集 ...

  4. BZOJ 1097: [POI2007]旅游景点atr [DP 状压 最短路]

    传送门 题意: 一个无向图,从$1$到$n$,要求必须经过$2,3,...,k+1$,给出一些限制关系,要求在经过$v \le k+1$之前必须经过$u \le k+1$ 求最短路 预处理出$1... ...

  5. 【BZOJ】1097: [POI2007]旅游景点atr(spfa+状压dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1097 首先还是我很sb....想到了分层图想不到怎么串起来,,,以为用拓扑序搞转移,,后来感到不行. ...

  6. BZOJ1097: [POI2007]旅游景点atr

    ..k次最短路后,考虑如何满足先走一些点 用状压dp,每一个点考虑它所需要经过的点a[i],当当前走过的点包含a[i]时,i 这个点才可以到达. 写的时候用记忆化搜索. #include<bit ...

  7. 【BZOJ1097】[POI2007]旅游景点atr 最短路+状压DP

    [BZOJ1097][POI2007]旅游景点atr Description FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺 ...

  8. [POI2007]旅游景点atr BZOJ1097

    分析: 我们可以考虑,因为我们必须经过这些节点,那么我们可以将它状压,并且我们因为可以重复走,只是要求停顿前后,不要求遍历前后,那么我们之间存一下点与点之间的最短路,之后每次转移一下就可以了. f[i ...

  9. 【bzoj1097】[POI2007]旅游景点atr 状压dp+堆优化Dijkstra

    题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个 ...

随机推荐

  1. C++编写DLL文件

    动态链接库DLL文件与EXE文件一样也是可执行文件,但是DLL也被称为库,因为里面封装了各种类.函数之类的东西,就像一个库一样,存着很多东西,主要是用来调用的.调用方式主要分为两种:隐式(通过lib文 ...

  2. HTNL基础之二

    HTML实体字符 “<”:< “>”:> “空格”: ' / / '  “"”:"  “®”:®  “©”:© 列表 ①无序列表:列表用来在网页上组织信息, ...

  3. Python 【Debug排除程序故障】

    debug #排除程序故障 print()函数常和#号注释结合在一起用来debug 多行注释有两种快捷操作:1.在需要注释的多行代码块前后加一组三引号''' 2.选中代码后使用快捷键操作:Window ...

  4. 装饰器中functools的用处

    定义一个最简单的装饰器 def user_login_data(f): def wrapper(*args, **kwargs): return f(*args, **kwargs) return w ...

  5. 怎样判断浏览器是否支持canvas

    1. 如果网页必须使用canvas, 则需要告知用户更换或更新浏览器. 这时可以通过在<canvas>标签之间添加替代元素进行 <canvas id="c1"&g ...

  6. wireshark 分析过滤数据

    1.过滤IP,如来源IP或者目标IP等于某个IP例子:ip.src eq 192.168.1.107 or ip.dst eq 192.168.1.107或者ip.addr eq 192.168.1. ...

  7. DX使用随笔--NavBarControl

    1. Item图标大小显示 需要先设置此Item所在Group的属性GroupStyle的值为LargeImageText.

  8. vue项目前端限制页面长时间未操作超时退出到登录页

    之前项目超时判断是后台根据token判断的,这样判断需要请求接口才能得到返回结果,这样就出现页面没有接口请求时还可以点击,有接口请求时才会退出 现在需要做到的效果是:页面超过30分钟未操作时,无论点击 ...

  9. @ComponentScan注解及其XML配置

    开发中会经常使用包扫描,只要标注了@Controller.@Service.@Repository,@Component 注解的类会自动加入到容器中,ComponentScan有注解和xml配置两种方 ...

  10. 前端基础(三):JavaScript

    JavaScript概述 JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中),后将其改名ScriptEase(客 ...