题目地址:HDU 3468

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

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

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

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

代码例如以下:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include<algorithm> using namespace std;
const int INF=0x3f3f3f3f;
int head[12001], source, sink, nv, cnt;
int cur[12001], num[12001], pre[12001], d[12001];
int d1[60][12001], dd[60], vis[101][101], n, m, goad[12000], id[110][110], tot;
int jx[]= {0,0,1,-1};
int jy[]= {1,-1,0,0};
char mp[110][110];
struct node
{
int u, v, cap, next;
} edge[10000000];
void add(int u, int v, int cap)
{
edge[cnt].v=v;
edge[cnt].cap=cap;
edge[cnt].next=head[u];
head[u]=cnt++; edge[cnt].v=u;
edge[cnt].cap=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
void bfs()
{
memset(d,-1,sizeof(d));
memset(num,0,sizeof(num));
queue<int>q;
q.push(sink);
d[sink]=0;
num[0]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(d[v]==-1)
{
d[v]=d[u]+1;
num[d[v]]++;
q.push(v);
}
}
}
}
void isap()
{
memcpy(cur,head,sizeof(cur));
bfs();
int flow=0, u=pre[source]=source, i;
while(d[source]<nv)
{
if(u==sink)
{
int f=INF, pos;
for(i=source;i!=sink;i=edge[cur[i]].v)
{
if(f>edge[cur[i]].cap)
{
f=edge[cur[i]].cap;
pos=i;
}
}
for(i=source;i!=sink;i=edge[cur[i]].v)
{
edge[cur[i]].cap-=f;
edge[cur[i]^1].cap+=f;
}
flow+=f;
u=pos;
}
for(i=cur[u];i!=-1;i=edge[i].next)
{
if(d[edge[i].v]+1==d[u]&&edge[i].cap) break;
}
if(i!=-1)
{
cur[u]=i;
pre[edge[i].v]=u;
u=edge[i].v;
}
else
{
if(--num[d[u]]==0) break;
int mind=nv;
for(i=head[u];i!=-1;i=edge[i].next)
{
if(mind>d[edge[i].v]&&edge[i].cap)
{
mind=d[edge[i].v];
cur[u]=i;
}
}
d[u]=mind+1;
num[d[u]]++;
u=pre[u];
}
}
printf("%d\n",flow);
}
int getid(char c)
{
if(c>='A'&&c<='Z')
return c-'A'+1;
else if(c>='a'&&c<='z')
return c-'a'+27;
else
return 0;
} void bfs(int x, int y)
{
int i;
queue<int>q;
q.push(x*m+y);
memset(vis,0,sizeof(vis));
vis[x][y]=1;
d1[id[x][y]][x*m+y]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
int a=u/m;
int b=u%m;
for(i=0; i<4; i++)
{
int c=a+jx[i];
int d=b+jy[i];
if(c>=0&&c<n&&d>=0&&d<m&&!vis[c][d]&&mp[c][d]!='#')
{
vis[c][d]=1;
d1[id[x][y]][c*m+d]=d1[id[x][y]][a*m+b]+1;
q.push(c*m+d);
if(id[c][d]==id[x][y]+1)
{
dd[id[x][y]]=d1[id[x][y]][c*m+d];
}
}
}
}
}
int main()
{
int i, j, nu;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(head,-1,sizeof(head));
memset(d1,INF,sizeof(d1));
memset(dd,INF,sizeof(dd));
cnt=0;
nu=0;
tot=0;
for(i=0; i<n; i++)
{
scanf("%s",mp[i]);
for(j=0; j<m; j++)
{
if(mp[i][j]=='*')
{
goad[nu++]=i*m+j;
}
id[i][j]=getid(mp[i][j]);
if(id[i][j])
tot++;
}
}
for(i=0; i<n; i++)
{
for(j=0; j<m; j++)
{
if(id[i][j])
{
bfs(i,j);
}
}
}
for(i=1; i<tot; i++)
{
if(dd[i]==INF)
{
printf("-1\n");
break;
}
}
if(i<tot)
continue ;
source=0;
sink=tot+nu+1;
nv=sink+1;
for(i=1;i<tot;i++)
{
add(source,i,1);
}
for(i=1;i<=nu;i++)
{
add(i+tot,sink,1);
}
for(i=1; i<tot; i++)
{
for(j=0; j<nu; j++)
{
if(d1[i][goad[j]]+d1[i+1][goad[j]]==dd[i])
{
add(i,j+tot+1,1);
}
}
}
isap();
}
return 0;
}

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. WPF按钮清空自带样式,以及透明按钮时,Grid的Background属性设置引起"点击"问题.

    1.空样式按钮 <Style x:Key="EmptyButtonStyle" TargetType="Button">            &l ...

  2. docker 导入下载模板

    <pre name="code" class="ruby">docker:/root# cat centos-6-x86.tar.gz | dock ...

  3. 京东区块排版负margin用法

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. [Oracle] - 性能优化工具(3) - ADDM

    ADDM 通过检查和分析AWR获取的数据来推断Oracle数据库中可能的问题.并给出优化建议. 获取ADDM的方法例如以下: @?/rdbms/admin/addmrpt.sql 以下能够看一个样例: ...

  5. iSCSI存储系统知识

    一.概述 SCSI 即小型计算机系统接口(Small Computer System Interface:简写:SCSI),一种用于计算机和外部设备之间(硬盘.光驱.软驱.打印机等)系统级接口的独立处 ...

  6. pagination分页插件

    最近做了个项目,有用到分页, 这类插件应该是很常用的, 虽然网上很多现成的分页插件, 但是还是想着自己写一个, 给自己积累点东西, 顺便练练手, 写了差不多3个小时左右, 代码如下: 代码: < ...

  7. 网络分析shell脚本(实时流量+连接统计)

    介绍一个强大的分析网络的shell脚本,此脚本是从EZHTTP拆分出来的,觉得有必要单独介绍下.脚本运行效果截图: 此脚本包含的功能有: 1.实时监控任意网卡的流量 2.统计10秒内平均流量 3.统计 ...

  8. css学习知识点

    各个前缀所代表的浏览器: Webkit: chrome, safari[也有可能是opera] Moz: 火狐 Ms: 主要是IE O: opera border-radius:  IE9  -web ...

  9. Javascript基础示例:用JS写简易版贪吃蛇(面向对象)

    废话不多说,代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...

  10. javascript 验证身份证

    /*身份证号码检索*/ function cardCheck(cartNo) { if (cartNo.val() === "") { return false; } else i ...