http://acm.hdu.edu.cn/showproblem.php?pid=2732

题意:给出两个地图,蜥蜴从一个柱子跳跃到另外一个地方,那么这个柱子就可能会坍塌,第一个地图是柱子可以容忍跳跃多少次(即从它为起点可以跳跃多少次,然后坍塌),第二个地图是蜥蜴的位置。还有一个跳跃距离d,即蜥蜴可以跳跃不超过d的距离(曼哈顿距离),如果跳到地图外面,即蜥蜴逃跑成功,问最终留下的蜥蜴数最少是多少。

思路:我觉得如果不是在做网络流套题应该想不到这是网络流。其实挺简单的建图。首先考虑蜥蜴的位置,和柱子的位置,如果柱子的位置有蜥蜴,那么这个柱子可以容忍的跳跃次数wi要-1,因为这个地方的蜥蜴必须跳走。然后把蜥蜴的位置,柱子的位置,和地图外边的位置存下来,蜥蜴和柱子拆点,形成一个S->lizard1->lizard2->pil1->pil2->out->T这样的网络。

1、如果蜥蜴可以直接跳到地图外,那么可以在lizard2和out之间连一条边,如果柱子可以跳到地图外,就在pil2和out之间连边,权值都为INF。

2、如果柱子之间如果距离在d之间,那么也可以连边,权值为将要跳到的柱子的wi。

3、如果蜥蜴可以跳到柱子,那么可以连边,权值为柱子的wi。

4、S和lizard1连边权值为1。

5、out和T连边权值为INF。

6、蜥蜴拆点权值为1,柱子拆点权值为wi。

这样就做完了。注意输出要仔细。

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
typedef long long LL;
struct Edge {
int v, nxt, cap;
Edge () {}
Edge (int v, int cap, int nxt) : v(v), cap(cap), nxt(nxt) {}
} edge[N];
struct Node {
int x, y;
friend bool operator < (const Node &a, const Node &b) {
return a.x < b.x;
}
} lizard[N], pil[N], out[N];
int head[N], tot, cur[N], gap[N], pre[N], dis[N], w[N], S, T; void Add(int u, int v, int cap) {
edge[tot] = Edge(v, cap, head[u]); head[u] = tot++;
edge[tot] = Edge(u, , head[v]); head[v] = tot++;
} int Cal(Node a, Node b) {
return abs(a.x - b.x) + abs(a.y - b.y);
} void BFS() {
memset(dis, -, sizeof(dis));
memset(gap, , sizeof(gap));
queue<int> que; que.push(T);
dis[T] = ; gap[]++;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
Edge& e = edge[i];
if(~dis[e.v]) continue;
dis[e.v] = dis[u] + ;
que.push(e.v);
gap[dis[e.v]]++;
}
}
} int ISAP(int n) {
BFS();
memcpy(cur, head, sizeof(cur));
int ans = , i, u = pre[S] = S;
while(dis[S] < n) {
if(u == T) {
int flow = INF, index;
for(i = S; i != T; i = edge[cur[i]].v)
if(edge[cur[i]].cap < flow) flow = edge[cur[i]].cap, index = i;
for(i = S; i != T; i = edge[cur[i]].v)
edge[cur[i]].cap -= flow, edge[cur[i]^].cap += flow;
ans += flow; u = index;
}
for(i = cur[u]; ~i; i = edge[i].nxt)
if(dis[edge[i].v] + == dis[u] && edge[i].cap > ) break;
if(~i) {
pre[edge[i].v] = u; cur[u] = i;
u = edge[i].v;
} else {
if(--gap[dis[u]] == ) break;
int md = n;
for(int i = head[u]; ~i; i = edge[i].nxt)
if(dis[edge[i].v] < md && edge[i].cap > )
md = dis[edge[i].v], cur[u] = i;
gap[dis[u] = md + ]++;
u = pre[u];
}
}
return ans;
} int main() {
int t, cas = ;
cin >> t;
while(t--) {
int n, d, m; char mp[][], s[][];
scanf("%d%d", &n, &d);
memset(head, -, sizeof(head)); tot = ;
int lzcnt = , picnt = , oucnt = ;
for(int i = ; i <= n; i++) scanf("%*c%s", mp[i] + );
m = strlen(mp[] + );
for(int i = ; i <= n; i++) {
scanf("%*c%s", s[i] + );
for(int j = ; j <= m; j++) {
if(s[i][j] == 'L') {
lizard[++lzcnt].x = i, lizard[lzcnt].y = j;
if(mp[i][j] - '' > ) {
pil[++picnt].x = i, pil[picnt].y = j, w[picnt] = mp[i][j] - '' - ; // 如果柱子位置有蜥蜴,那么流量要-1
}
} else if(mp[i][j] != '') {
pil[++picnt].x = i, pil[picnt].y = j, w[picnt] = mp[i][j] - '';
}
}
}
for(int i = ; i <= n; i++) {
out[++oucnt].x = i; out[oucnt].y = ;
out[++oucnt].x = i; out[oucnt].y = m + ;
}
for(int i = ; i <= m; i++) {
out[++oucnt].x = ; out[oucnt].y = i;
out[++oucnt].x = n + ; out[oucnt].y = i;
}
S = ; T = * lzcnt + * picnt + oucnt + ;
for(int i = ; i <= lzcnt; i++) Add(S, i, ), Add(i, i + lzcnt, ); // 源点和蜥蜴,蜥蜴拆点
for(int i = ; i <= oucnt; i++) Add( * lzcnt + * picnt + i, T, INF); // 边界点和汇点
for(int i = ; i <= picnt; i++) Add( * lzcnt + i, * lzcnt + picnt + i, w[i]); // 跳跃点拆点
for(int i = ; i <= lzcnt; i++) {
for(int j = ; j <= picnt; j++) {
if(Cal(lizard[i], pil[j]) <= d && Cal(lizard[i], pil[j]) != ) {
Add(i + lzcnt, j + * lzcnt, w[j]); // 蜥蜴的第二个点和跳跃点第一个点
}
}
for(int j = ; j <= oucnt; j++) {
if(Cal(lizard[i], out[j]) <= d) Add(i + lzcnt, j + lzcnt * + picnt * , INF);
}
}
for(int i = ; i <= picnt; i++) {
for(int j = i + ; j <= picnt; j++) {
if(Cal(pil[i], pil[j]) <= d) {
Add(i + * lzcnt + picnt, j + * lzcnt, INF); // 跳跃点
Add(j + * lzcnt + picnt, i + * lzcnt, INF);
}
}
for(int j = ; j <= oucnt; j++) {
if(Cal(pil[i], out[j]) <= d) Add(i + lzcnt * + picnt, j + lzcnt * + picnt * , INF);
}
}
int ans = lzcnt - ISAP(T + );
printf("Case #%d: ", ++cas);
if(ans < ) {
if(ans <= ) printf("no lizard was ");
else printf("1 lizard was ");
} else {
printf("%d lizards were ", ans);
}
puts("left behind.");
}
return ;
}

#看了一下别人的思路,一开始自己也想的差不多那样,但是硬是调不出来,就用了这么复杂方法,觉得自己没救了,好简单的思路。

S->pil1->pil2->T,如果柱子上有蜥蜴就将这个点和S连,如果在该柱子可以跳出去,那么就将这个点和T相连,然后和能够相连的柱子连边就好了。再写一遍

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
typedef long long LL;
struct Edge {
int v, nxt, cap;
Edge () {}
Edge (int v, int cap, int nxt) : v(v), cap(cap), nxt(nxt) {}
} edge[N];
struct Node {
int x, y, w, flag;
} pil[N];
int head[N], tot, cur[N], gap[N], pre[N], dis[N], S, T; void Add(int u, int v, int cap) {
edge[tot] = Edge(v, cap, head[u]); head[u] = tot++;
edge[tot] = Edge(u, , head[v]); head[v] = tot++;
} int Cal(Node a, Node b) {
return abs(a.x - b.x) + abs(a.y - b.y);
} void BFS() {
memset(dis, -, sizeof(dis));
memset(gap, , sizeof(gap));
queue<int> que; que.push(T);
dis[T] = ; gap[]++;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
Edge& e = edge[i];
if(~dis[e.v]) continue;
dis[e.v] = dis[u] + ;
que.push(e.v);
gap[dis[e.v]]++;
}
}
} int ISAP(int n) {
BFS();
memcpy(cur, head, sizeof(cur));
int ans = , i, u = pre[S] = S;
while(dis[S] < n) {
if(u == T) {
int flow = INF, index;
for(i = S; i != T; i = edge[cur[i]].v)
if(edge[cur[i]].cap < flow) flow = edge[cur[i]].cap, index = i;
for(i = S; i != T; i = edge[cur[i]].v)
edge[cur[i]].cap -= flow, edge[cur[i]^].cap += flow;
ans += flow; u = index;
}
for(i = cur[u]; ~i; i = edge[i].nxt)
if(dis[edge[i].v] + == dis[u] && edge[i].cap > ) break;
if(~i) {
pre[edge[i].v] = u; cur[u] = i;
u = edge[i].v;
} else {
if(--gap[dis[u]] == ) break;
int md = n;
for(int i = head[u]; ~i; i = edge[i].nxt)
if(dis[edge[i].v] < md && edge[i].cap > )
md = dis[edge[i].v], cur[u] = i;
gap[dis[u] = md + ]++;
u = pre[u];
}
}
return ans;
} int main() {
int t, cas = ;
cin >> t;
while(t--) {
int n, d, m; char mp[][], s[][];
scanf("%d%d", &n, &d);
memset(head, -, sizeof(head)); tot = ;
int cnt = , tol = ;
for(int i = ; i <= n; i++) {
scanf("%s", s[i] + );
m = strlen(s[i] + );
for(int j = ; j <= m; j++)
if(s[i][j] != '') pil[++cnt].x = i, pil[cnt].y = j, pil[cnt].w = s[i][j] - '';
}
for(int i = ; i <= n; i++) {
scanf("%s", mp[i] + );
for(int j = ; j <= m; j++) {
for(int k = ; k <= cnt; k++) {
if(pil[k].x == i && pil[k].y == j) {
if(mp[i][j] == 'L') pil[k].flag = , tol++;
else pil[k].flag = ;
break;
}
}
}
}
S = , T = * cnt + ;
for(int i = ; i <= cnt; i++) {
Add(i, i + cnt, pil[i].w);
if(pil[i].flag == ) Add(S, i, );
for(int j = i + ; j <= cnt; j++) {
if(Cal(pil[i], pil[j]) <= d) {
Add(i + cnt, j, INF);
Add(j + cnt, i, INF);
}
}
if(pil[i].x <= d || pil[i].y <= d || n - pil[i].x < d || m - pil[i].y < d)
Add(i + cnt, T, INF);
} int ans = tol - ISAP(T + );
printf("Case #%d: ", ++cas);
if(ans < ) {
if(ans <= ) printf("no lizard was ");
else printf("1 lizard was ");
} else {
printf("%d lizards were ", ans);
}
puts("left behind.");
}
return ;
}

HDU 2732:Leapin' Lizards(最大流)的更多相关文章

  1. hdu 2732 Leapin' Lizards 最大流 拆点 建图

    题目链接 题意 给定一张网格,格子中有些地方有柱子,有些柱子上面有蜥蜴. 每个柱子只能承受有限只蜥蜴从上面经过.每只蜥蜴每次能走到相距曼哈顿距离\(\leq k\)的格子中去. 问有多少只蜥蜴能走出网 ...

  2. hdu 2732 Leapin' Lizards (最大流 拆点建图)

    Problem Description Your platoon of wandering lizards has entered a strange room in the labyrinth yo ...

  3. POJ 2711 Leapin' Lizards / HDU 2732 Leapin' Lizards / BZOJ 1066 [SCOI2007]蜥蜴(网络流,最大流)

    POJ 2711 Leapin' Lizards / HDU 2732 Leapin' Lizards / BZOJ 1066 [SCOI2007]蜥蜴(网络流,最大流) Description Yo ...

  4. HDU 2732 Leapin' Lizards(最大流)

    http://acm.hdu.edu.cn/showproblem.php?pid=2732 题意: 给出n行的网格,还有若干只蜥蜴,每只蜥蜴一开始就在一个格子之中,并且给出蜥蜴每次的最大跳跃长度d. ...

  5. hdu 2732 Leapin' Lizards(最大流)Mid-Central USA 2005

    废话: 这道题不难,稍微构造一下图就可以套最大流的模板了.但是我还是花了好久才解决.一方面是最近确实非常没状态(托词,其实就是最近特别颓废,整天玩游戏看小说,没法静下心来学习),另一方面是不够细心,输 ...

  6. HDU - 2732 Leapin' Lizards (拆点最大流)

    题意:有N*M的矩形,每个格点有一个柱子,每根柱子有高度c,允许蜥蜴经过这根柱子c次,开始有一些蜥蜴在某些柱子上,它们要跳出这个矩形,每步最大能跳d个单位,求最少有多少蜥蜴不能跳出这个矩形. 分析:转 ...

  7. HDU 2732 Leapin' Lizards

    网络最大流+拆点.输出有坑!!! #include<cstdio> #include<cstring> #include<string> #include<c ...

  8. HDU 2732 Leapin&#39; Lizards(拆点+最大流)

    HDU 2732 Leapin' Lizards 题目链接 题意:有一些蜥蜴在一个迷宫里面,有一个跳跃力表示能跳到多远的柱子,然后每根柱子最多被跳一定次数,求这些蜥蜴还有多少是不管怎样都逃不出来的. ...

  9. HDU2732 Leapin' Lizards —— 最大流、拆点

    题目链接:https://vjudge.net/problem/HDU-2732 Leapin' Lizards Time Limit: 2000/1000 MS (Java/Others)    M ...

  10. Leapin' Lizards [HDU - 2732]【网络流最大流】

    题目链接 网络流直接最大流就是了,只是要拆点小心一个点的流超出了原本的正常范围才是. #include <iostream> #include <cstdio> #includ ...

随机推荐

  1. Objective-C数据保存和读取

    一.NSCoding协议中的Archiving和Unarchiving (1)Archiving一个object,会记录这个对象的所有的properties到filesystem: (2)Unarch ...

  2. js 转码 和 .Net 后台解码

    为防止 中文乱码,js传值要转码,当js 用 escape() 转码时,.Net 后台可以用 HttpUtility.UrlDecode() 进行解码. 例如:   document.cookie = ...

  3. JMeter学习-028-JMeter默认jmx脚本分发目录(路径)定制

    我们在分布式执行参数化脚本时,为尽可能多的利用Slave资源,尽可能将参数文件配置为相对路径,以更好的去适配Slave环境.与此同时,每台Slave的服务jmeter -s 启动的路径可能不尽相同,同 ...

  4. 常用git命令纪录

    git branch xxx 新建分支xxx git branch -a 查看所有分支(包括远程) git remote add origin http://xxx.git  在本地添加一个远程仓库, ...

  5. 限制EditText最多输入多少汉字

    mInputEditText.setFilters(new InputFilter[]{new InputLengthFilter(MAX_INPUT_SIZE)}); public class In ...

  6. JAVA 实现FTP上传下载(sun.net.ftp.FtpClient)

    package com.why.ftp; import java.io.DataInputStream; import java.io.File; import java.io.FileInputSt ...

  7. XSLT简介

    什么是? http://www.w3school.com.cn/xsl/xsl_intro.asp XSLT 是一种用于将 XML 文档转换为 XHTML 文档或其他 XML 文档的语言. XPath ...

  8. Leetcode: Convex Polygon

    Given a list of points that form a polygon when joined sequentially, find if this polygon is convex ...

  9. 向指定URL发送GET方法获取资源,编码问题。 Rest风格

    http编码.今天遇到获取网页上的数据,用HTTP的GET请求访问url获取资源,网上有相应的方法.以前一直不知道什么事rest风格,现在我想就是开一个Controller,然后使人可以调用你的后台代 ...

  10. IOS轮播图

    轮播图播放的主要技术在于: cell的封装.这里采用UICollectionViewCell实现. #import <UIKit/UIKit.h> @interface CircleVie ...