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. NGUI 层级关系控制

    NGUI元素的遮挡情况是不依赖空间关系,所以在NGUI上添加特效有时候特别蛋疼,特别是美术同学还要依赖空间关系来控制特效效果,那先看看看NGUI的层级是怎么处理的,不过下面的描述都是针对单个相机下的P ...

  2. JMeter 响应文本乱码处理

    首次安装Jmeter后,会出现响应文本乱码现象,处理办法如下: (1)修改默认编码方式 Jmeter安装目录/bin/jmeter.properties中sampleresult.default.en ...

  3. 【java基础学习】网络编程

    网络编程 InetAddress tcp udp

  4. HTML:document.activeElement

    今天遇到一个很郁闷的问题: document.activeElement获取当前获得焦点的元素,在chrome总是得到body,后来经过试验得到结果如下: document.activeElement ...

  5. iscoll制作顶部可以左右滑动的tab

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  6. http协议中用于上传多个文件的 multipart 字段

    大家好,我是许飞,微软拼音的开发实习生.在网络编程中,经常用到从服务器上“下载”一些数据,有时却要向服务器“上传”数据.曾在一个原型中使用了“multipart/form-data”格式向Web服务器 ...

  7. oracle数据库连接慢的问题

    1.现象 工程为spring+mybatis+xfire,webservice工程服务,实现的接口数据功能 2.修复方法 经过各种尝试: 1.重新部署工程     无果 2.重新部署tomcat   ...

  8. const

     const int i = 20; int const i = 20; 这两个语句是完全相同的:const与int哪个写在前面都不影响语义. 所以: const int *p; int const ...

  9. C# MVC 页面静态化导致的问题

    在设置页面静态化的路由,代码如 //静态路由 routes.MapRoute( name: "html", url: "{controller}/{action}.htm ...

  10. php页面如何增加下载软件功能

    php <?php $array = parse_ini_file("sample.ini"); ?> <a id="btnDownloadFull&q ...