题目地址: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. delphi SysErrorMessage 函数和系统错误信息表 good

    在看 API 文档时, 我们经常见到 GetLastError; 它可以返回操作后系统给的提示. 但 GetLastError 返回的只是一个信息代码, 如何返回对应的具体信息呢? FormatMes ...

  2. 转自:Python函数式编程指南(二):函数

    2. 从函数开始 2.1. 定义一个函数 如下定义了一个求和函数: 1 2 def add(x, y):     return x + y 关于参数和返回值的语法细节可以参考其他文档,这里就略过了. ...

  3. Multipart/form-data POST文件上传详解(转)

    Multipart/form-data POST文件上传详解 理论 简单的HTTP POST 大家通过HTTP向服务器发送POST请求提交数据,都是通过form表单提交的,代码如下: <form ...

  4. Linux学习之十三、快捷键与通配符、数据流重导向

    通配符与特殊符号 接下来让我们利用通配符来玩些东西吧!首先,利用通配符配合 ls 找檔名看看: [root@www ~]# LANG=C              <==由于与编码有关,先配置语 ...

  5. error: C2664: “zajiao::zajiao(const zajiao &)”: 无法将参数 1 从“const char [12]”转换为“char *”

    原本打算在QT用一个字符串"ABCDEF12345"作为类zajiao的构造函数的参数,用来创建类zajiao的对象zajiao1. zajiao zajiao1("AB ...

  6. vpn pptp配置

    安装 yum install pptpd 配置pptpd 改动/etc/pptpd.conf设置 localip 192.168.20.1 remoteip 192.168.20.234-238,19 ...

  7. Android开发8:UI组件TextView,EditText,Button

    版本:Android4.3 API18 学习整理:liuxinming TextView 概述 TextView直接继承了View(EditText.Button两个UI组件类的父类) TextVie ...

  8. 动画原理——绘画API

    书籍名称:HTML5-Animation-with-JavaScript 书籍源码:https://github.com/lamberta/html5-animation 1.canvas的conte ...

  9. android webview点击返回键返回上一级activity

    android webview点击返回键返回上一个activity @Override public boolean onKeyDown(int keyCode, KeyEvent event) { ...

  10. 十全大补DBA学习资源

    学习oracle已经有1年多了,从开始的菜鸟到现在的DBA,一路走来~迷茫过.兴奋过.但我仍然会在DBA的道路上走下去!oracle要学的有很多,会遇到很多难题,网上有很多学习oracle好的学习资料 ...