题目地址:HDU 3468

这道题的关键在于能想到用网络流。然后还要想到用bfs来标记最短路中的点。

首先标记方法是,对每个集合点跑一次bfs,记录全部点到该点的最短距离。然后对于随意一对起始点来说,仅仅要这个点到起点的最短距离+该点到终点的最短距离==起点到终点的最短距离,就说明这点在某条从起点到终点的最短路上。

然后以集合点建X集,宝物点建Y集构造二分图,将从某集合点出发的最短路中经过宝物点与该集合点连边。剩下的用二分匹配算法或最大流算法都能够。(为什么我的最大流比二分匹配跑的还要快。。。。。。。)。

题目有一点须要注意,就是当从集合点i到i+1没有路的时候,要输出-1.

代码例如以下:

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <math.h>
  6. #include <ctype.h>
  7. #include <queue>
  8. #include <map>
  9. #include<algorithm>
  10.  
  11. using namespace std;
  12. const int INF=0x3f3f3f3f;
  13. int head[12001], source, sink, nv, cnt;
  14. int cur[12001], num[12001], pre[12001], d[12001];
  15. int d1[60][12001], dd[60], vis[101][101], n, m, goad[12000], id[110][110], tot;
  16. int jx[]= {0,0,1,-1};
  17. int jy[]= {1,-1,0,0};
  18. char mp[110][110];
  19. struct node
  20. {
  21. int u, v, cap, next;
  22. } edge[10000000];
  23. void add(int u, int v, int cap)
  24. {
  25. edge[cnt].v=v;
  26. edge[cnt].cap=cap;
  27. edge[cnt].next=head[u];
  28. head[u]=cnt++;
  29.  
  30. edge[cnt].v=u;
  31. edge[cnt].cap=0;
  32. edge[cnt].next=head[v];
  33. head[v]=cnt++;
  34. }
  35. void bfs()
  36. {
  37. memset(d,-1,sizeof(d));
  38. memset(num,0,sizeof(num));
  39. queue<int>q;
  40. q.push(sink);
  41. d[sink]=0;
  42. num[0]=1;
  43. while(!q.empty())
  44. {
  45. int u=q.front();
  46. q.pop();
  47. for(int i=head[u];i!=-1;i=edge[i].next)
  48. {
  49. int v=edge[i].v;
  50. if(d[v]==-1)
  51. {
  52. d[v]=d[u]+1;
  53. num[d[v]]++;
  54. q.push(v);
  55. }
  56. }
  57. }
  58. }
  59. void isap()
  60. {
  61. memcpy(cur,head,sizeof(cur));
  62. bfs();
  63. int flow=0, u=pre[source]=source, i;
  64. while(d[source]<nv)
  65. {
  66. if(u==sink)
  67. {
  68. int f=INF, pos;
  69. for(i=source;i!=sink;i=edge[cur[i]].v)
  70. {
  71. if(f>edge[cur[i]].cap)
  72. {
  73. f=edge[cur[i]].cap;
  74. pos=i;
  75. }
  76. }
  77. for(i=source;i!=sink;i=edge[cur[i]].v)
  78. {
  79. edge[cur[i]].cap-=f;
  80. edge[cur[i]^1].cap+=f;
  81. }
  82. flow+=f;
  83. u=pos;
  84. }
  85. for(i=cur[u];i!=-1;i=edge[i].next)
  86. {
  87. if(d[edge[i].v]+1==d[u]&&edge[i].cap) break;
  88. }
  89. if(i!=-1)
  90. {
  91. cur[u]=i;
  92. pre[edge[i].v]=u;
  93. u=edge[i].v;
  94. }
  95. else
  96. {
  97. if(--num[d[u]]==0) break;
  98. int mind=nv;
  99. for(i=head[u];i!=-1;i=edge[i].next)
  100. {
  101. if(mind>d[edge[i].v]&&edge[i].cap)
  102. {
  103. mind=d[edge[i].v];
  104. cur[u]=i;
  105. }
  106. }
  107. d[u]=mind+1;
  108. num[d[u]]++;
  109. u=pre[u];
  110. }
  111. }
  112. printf("%d\n",flow);
  113. }
  114. int getid(char c)
  115. {
  116. if(c>='A'&&c<='Z')
  117. return c-'A'+1;
  118. else if(c>='a'&&c<='z')
  119. return c-'a'+27;
  120. else
  121. return 0;
  122. }
  123.  
  124. void bfs(int x, int y)
  125. {
  126. int i;
  127. queue<int>q;
  128. q.push(x*m+y);
  129. memset(vis,0,sizeof(vis));
  130. vis[x][y]=1;
  131. d1[id[x][y]][x*m+y]=0;
  132. while(!q.empty())
  133. {
  134. int u=q.front();
  135. q.pop();
  136. int a=u/m;
  137. int b=u%m;
  138. for(i=0; i<4; i++)
  139. {
  140. int c=a+jx[i];
  141. int d=b+jy[i];
  142. if(c>=0&&c<n&&d>=0&&d<m&&!vis[c][d]&&mp[c][d]!='#')
  143. {
  144. vis[c][d]=1;
  145. d1[id[x][y]][c*m+d]=d1[id[x][y]][a*m+b]+1;
  146. q.push(c*m+d);
  147. if(id[c][d]==id[x][y]+1)
  148. {
  149. dd[id[x][y]]=d1[id[x][y]][c*m+d];
  150. }
  151. }
  152. }
  153. }
  154. }
  155. int main()
  156. {
  157. int i, j, nu;
  158. while(scanf("%d%d",&n,&m)!=EOF)
  159. {
  160. memset(head,-1,sizeof(head));
  161. memset(d1,INF,sizeof(d1));
  162. memset(dd,INF,sizeof(dd));
  163. cnt=0;
  164. nu=0;
  165. tot=0;
  166. for(i=0; i<n; i++)
  167. {
  168. scanf("%s",mp[i]);
  169. for(j=0; j<m; j++)
  170. {
  171. if(mp[i][j]=='*')
  172. {
  173. goad[nu++]=i*m+j;
  174. }
  175. id[i][j]=getid(mp[i][j]);
  176. if(id[i][j])
  177. tot++;
  178. }
  179. }
  180. for(i=0; i<n; i++)
  181. {
  182. for(j=0; j<m; j++)
  183. {
  184. if(id[i][j])
  185. {
  186. bfs(i,j);
  187. }
  188. }
  189. }
  190. for(i=1; i<tot; i++)
  191. {
  192. if(dd[i]==INF)
  193. {
  194. printf("-1\n");
  195. break;
  196. }
  197. }
  198. if(i<tot)
  199. continue ;
  200. source=0;
  201. sink=tot+nu+1;
  202. nv=sink+1;
  203. for(i=1;i<tot;i++)
  204. {
  205. add(source,i,1);
  206. }
  207. for(i=1;i<=nu;i++)
  208. {
  209. add(i+tot,sink,1);
  210. }
  211. for(i=1; i<tot; i++)
  212. {
  213. for(j=0; j<nu; j++)
  214. {
  215. if(d1[i][goad[j]]+d1[i+1][goad[j]]==dd[i])
  216. {
  217. add(i,j+tot+1,1);
  218. }
  219. }
  220. }
  221. isap();
  222. }
  223. return 0;
  224. }

HDU 3468 Treasure Hunting(BFS+网络流之最大流)的更多相关文章

  1. 【网络流】 HDU 3468 Treasure Hunting

    题意: A-Z&&a-z 表示 集结点 从A点出发经过 最短步数 走到下一个集结点(A的下一个集结点为B ,Z的下一个集结点为a) 的路上遇到金子(*)则能够捡走(一个点仅仅能捡一次) ...

  2. HDU 3338 Kakuro Extension (网络流,最大流)

    HDU 3338 Kakuro Extension (网络流,最大流) Description If you solved problem like this, forget it.Because y ...

  3. HDU 4280 Island Transport(网络流,最大流)

    HDU 4280 Island Transport(网络流,最大流) Description In the vast waters far far away, there are many islan ...

  4. HDU 3641 Treasure Hunting(阶乘素因子分解+二分)

    题目链接:pid=3641">传送门 题意: 求最小的 ( x! ) = 0 mod (a1^b1*a2^b2...an^bn) 分析: 首先吧a1~an进行素因子分解,然后统计下每一 ...

  5. hdu 3641 Treasure Hunting 强大的二分

    /** 大意:给定一组ai,bi . m = a1^b1 *a2^b2 * a3^ b3 * a4^b4*...*ai^bi 求最小的x!%m =0 思路: 将ai 质因子分解,若是x!%m=0 那么 ...

  6. HDU 3605Escape(缩点+网络流之最大流)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3605 本来打算昨天写两道题的,结果这个题卡住了,最后才发现是最后的推断条件出错了,推断满流的条件应该是 ...

  7. HDU 3416 Marriage Match IV (最短路径,网络流,最大流)

    HDU 3416 Marriage Match IV (最短路径,网络流,最大流) Description Do not sincere non-interference. Like that sho ...

  8. HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)

    HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...

  9. HDU 3605 Escape (网络流,最大流,位运算压缩)

    HDU 3605 Escape (网络流,最大流,位运算压缩) Description 2012 If this is the end of the world how to do? I do not ...

随机推荐

  1. jenkins中Deploy to container Plugin插件发布配置

    参数详解: 第一项(WAR/EAR files):是war包的相对路径(相对于工作区路径,即在工作区中war包的相对路径.)如我的maven执行完成之后会在工作区的target目录下生成项目.war, ...

  2. 设置windows窗口半透明(使用SetLayeredWindowAttributes API函数)

    所需函数原型:BOOL WINAPI SetLayeredWindowAttributes(HWND hWnd,  COLORREFcrKey,  BYTE bAlpha,  DWORD flag); ...

  3. 图片和提交servlet的相对和绝对路径

    xx.jsp在根目录下,图片的路径为:<img height="33" src="images/enter.gif" width="148&qu ...

  4. SQL server指定随机数范围

    declare @randnum int=0declare @startnum int =0declare @endnum int=0 set @startnum = 150 set @endnum ...

  5. linux 和unix 的区别

    Linux与Unix的区别  某些PC机的Unix和Linux在实现方面相类似.几乎所有的商业Unix版本都基本支持同样的软件.程序设计环境和网络特性.然而,Linux和Unix的商业版本依然存在许多 ...

  6. Spring、Bean 的作用域

    Singleton作用域(默认) 当一个bean的作用域为singleton,那么Spring Ioc容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则 ...

  7. hdu 2604 Queuing(矩阵快速幂乘法)

    Problem Description Queues and Priority Queues are data structures which are known to most computer ...

  8. Mysql 计算时间间隔函数

    #计算两个时间的间隔 #计算间隔天数 select TIMESTAMPDIFF(day,'2014-06-01',date(now())) #计算间隔月数 select TIMESTAMPDIFF(m ...

  9. CSS ::before 和 ::after 伪元素用法

    CSS 有两个说不上常用的伪类 :before 和 :after,偶尔会被人用来添加些自定义格式什么的,但是它们的功用不仅于此.前几天发现了 Creative Link Effects 这个非常有意思 ...

  10. js的this几种用法

    1.普通的函数调用 此时指的是全局对象 function aaa(){ this.x=1;}aaa();alert(x) 2.对象内的方法this调用 此时指的是上一级对象 var aaa={ zz: ...