HDU 3468 Treasure Hunting(BFS+网络流之最大流)
题目地址: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+网络流之最大流)的更多相关文章
- 【网络流】 HDU 3468 Treasure Hunting
题意: A-Z&&a-z 表示 集结点 从A点出发经过 最短步数 走到下一个集结点(A的下一个集结点为B ,Z的下一个集结点为a) 的路上遇到金子(*)则能够捡走(一个点仅仅能捡一次) ...
- HDU 3338 Kakuro Extension (网络流,最大流)
HDU 3338 Kakuro Extension (网络流,最大流) Description If you solved problem like this, forget it.Because y ...
- HDU 4280 Island Transport(网络流,最大流)
HDU 4280 Island Transport(网络流,最大流) Description In the vast waters far far away, there are many islan ...
- HDU 3641 Treasure Hunting(阶乘素因子分解+二分)
题目链接:pid=3641">传送门 题意: 求最小的 ( x! ) = 0 mod (a1^b1*a2^b2...an^bn) 分析: 首先吧a1~an进行素因子分解,然后统计下每一 ...
- hdu 3641 Treasure Hunting 强大的二分
/** 大意:给定一组ai,bi . m = a1^b1 *a2^b2 * a3^ b3 * a4^b4*...*ai^bi 求最小的x!%m =0 思路: 将ai 质因子分解,若是x!%m=0 那么 ...
- HDU 3605Escape(缩点+网络流之最大流)
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3605 本来打算昨天写两道题的,结果这个题卡住了,最后才发现是最后的推断条件出错了,推断满流的条件应该是 ...
- HDU 3416 Marriage Match IV (最短路径,网络流,最大流)
HDU 3416 Marriage Match IV (最短路径,网络流,最大流) Description Do not sincere non-interference. Like that sho ...
- HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)
HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...
- HDU 3605 Escape (网络流,最大流,位运算压缩)
HDU 3605 Escape (网络流,最大流,位运算压缩) Description 2012 If this is the end of the world how to do? I do not ...
随机推荐
- 常用在线工具及API网址总结
1.小图标在线查找 https://www.iconfinder.com/ 2.在线做图,Flowchart流程图,BPMN图,Org组织结构图等 http://www.processon.com/ ...
- MySQL RR隔离 读一致性
MySQL RR 模式下 事务隔离问题: Session 1: mysql> select * from test; +------+------+ | id | name | +------+ ...
- 百度静态资源(JS)公共库
例如: chosen http://apps.bdimg.com/libs/chosen/1.1.0/chosen.jquery.min.js classlist http://apps ...
- 全国计算机等级考试二级教程-C语言程序设计_第8章_地址和指针
面试: unsigned int *p1 = # int *p2 = # #define _CRT_SECURE_NO_WARNINGS #include<std ...
- DDL
在DDL(Data Definition Language)中,创建.删除.修改使用create.drop.alter关键字 数据库的创建 create database 数据库名选择数据库 use ...
- jQuery源码笔记——二
jQuery选择这样返回对象 var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, con ...
- 让ie支持placeholder属性,一段js搞定
placeholder属性真的是超级好用的新属性,可惜,只有新版浏览器才支持,为了写出输入框贴心提示,老方法就是加span标签覆盖,营造出placeholder提示的感觉,现在安利一款好用的js,好用 ...
- Android入门——UI(8)——Fragment(2)
先演示一下如何在一个activity中放置两个Fragment,先定义两个Fragment <?xml version="1.0" encoding="utf-8& ...
- L6 Shell
写出以下shell脚本1 判定一个用参数指定的文件是否为可执行,如果不是,则改为可执行#!/bin/bash if [ -x $1 ]then echo "OK"else echo ...
- JAVA注释方式--目前用的
代码整洁,规范,可读,注释是关键之一. 1.整个类文件注释 注释结构:/* * @(#){类名称}.java {创建时间} * * {某人或某公司具有完全的版权} * {使用者必须经过许可 ...