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. SVN中trunk、branches、tag的使用

     我相信初学开发在SVN作为版本管理时,都估计没可能考虑到如何灵活的运用SVN来管理开发代码的版本,下面我就摘录一篇文章来简单说明SVN里的trunk,branched,tags这个三个文件目录的用法 ...

  2. Mock之easymock, powermock, and mockito

    easymock, powermock, and mockito Easymock Class Mocking Limitations To be coherent with interface mo ...

  3. KITTI数据集格式说明

    由于上一篇博客所提到的论文中的训练数据是KITTI的数据集,因此如果我想要用自己的数据集进行训练的话,就需要先弄清楚KITTI数据集的格式,在以下的网址找到了说明: 首先,数据描述中是这样的: 在以下 ...

  4. java 给指定时间加上天数or给当前日期加天数

    给指定日期加上天数: /** * 指定日期加上天数后的日期 * @param num 为增加的天数 * @param newDate 创建时间 * @return * @throws ParseExc ...

  5. [转]SQL SERVER – Importance of Database Schemas in SQL Server

    原文地址http://blog.sqlauthority.com/2009/09/07/sql-server-importance-of-database-schemas-in-sql-server/ ...

  6. sed 引入shell变量

    双单引号即可 1.eval sed ’s/$a/$b/’ filename2.sed "s/$a/$b/" filename3.sed ’s/’$a’/’$b’/’ filenam ...

  7. Android中如何查看内存

    文章参照自:http://stackoverflow.com/questions/2298208/how-to-discover-memory-usage-of-my-application-in-a ...

  8. Issue 0:发刊词

    最近读吴军博士的文章,很受感悟.知识的成体系地积累过程对一个人的素养提高很有帮助,所以打算开通这本电子期刊,以一周一篇文章的形式汇总今后的知识体系. 宗旨:及时和团队讨论,反馈:善于利用工具.时间越长 ...

  9. Java网络编程之流——readline()方法的bug

    readline()方法有一个隐含的bug,它不一定会把一个回车看作行的结束.相反,readline()只识别换行或回车/换行对.当在流中检测到回车时,readline()会在继续之前等待,查看下一个 ...

  10. Jquery 定时器 倒计时

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