HDU 2732:Leapin' Lizards(最大流)
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(最大流)的更多相关文章
- hdu 2732 Leapin' Lizards 最大流 拆点 建图
题目链接 题意 给定一张网格,格子中有些地方有柱子,有些柱子上面有蜥蜴. 每个柱子只能承受有限只蜥蜴从上面经过.每只蜥蜴每次能走到相距曼哈顿距离\(\leq k\)的格子中去. 问有多少只蜥蜴能走出网 ...
- hdu 2732 Leapin' Lizards (最大流 拆点建图)
Problem Description Your platoon of wandering lizards has entered a strange room in the labyrinth yo ...
- POJ 2711 Leapin' Lizards / HDU 2732 Leapin' Lizards / BZOJ 1066 [SCOI2007]蜥蜴(网络流,最大流)
POJ 2711 Leapin' Lizards / HDU 2732 Leapin' Lizards / BZOJ 1066 [SCOI2007]蜥蜴(网络流,最大流) Description Yo ...
- HDU 2732 Leapin' Lizards(最大流)
http://acm.hdu.edu.cn/showproblem.php?pid=2732 题意: 给出n行的网格,还有若干只蜥蜴,每只蜥蜴一开始就在一个格子之中,并且给出蜥蜴每次的最大跳跃长度d. ...
- hdu 2732 Leapin' Lizards(最大流)Mid-Central USA 2005
废话: 这道题不难,稍微构造一下图就可以套最大流的模板了.但是我还是花了好久才解决.一方面是最近确实非常没状态(托词,其实就是最近特别颓废,整天玩游戏看小说,没法静下心来学习),另一方面是不够细心,输 ...
- HDU - 2732 Leapin' Lizards (拆点最大流)
题意:有N*M的矩形,每个格点有一个柱子,每根柱子有高度c,允许蜥蜴经过这根柱子c次,开始有一些蜥蜴在某些柱子上,它们要跳出这个矩形,每步最大能跳d个单位,求最少有多少蜥蜴不能跳出这个矩形. 分析:转 ...
- HDU 2732 Leapin' Lizards
网络最大流+拆点.输出有坑!!! #include<cstdio> #include<cstring> #include<string> #include<c ...
- HDU 2732 Leapin' Lizards(拆点+最大流)
HDU 2732 Leapin' Lizards 题目链接 题意:有一些蜥蜴在一个迷宫里面,有一个跳跃力表示能跳到多远的柱子,然后每根柱子最多被跳一定次数,求这些蜥蜴还有多少是不管怎样都逃不出来的. ...
- HDU2732 Leapin' Lizards —— 最大流、拆点
题目链接:https://vjudge.net/problem/HDU-2732 Leapin' Lizards Time Limit: 2000/1000 MS (Java/Others) M ...
- Leapin' Lizards [HDU - 2732]【网络流最大流】
题目链接 网络流直接最大流就是了,只是要拆点小心一个点的流超出了原本的正常范围才是. #include <iostream> #include <cstdio> #includ ...
随机推荐
- SVN中trunk、branches、tag的使用
我相信初学开发在SVN作为版本管理时,都估计没可能考虑到如何灵活的运用SVN来管理开发代码的版本,下面我就摘录一篇文章来简单说明SVN里的trunk,branched,tags这个三个文件目录的用法 ...
- Mock之easymock, powermock, and mockito
easymock, powermock, and mockito Easymock Class Mocking Limitations To be coherent with interface mo ...
- KITTI数据集格式说明
由于上一篇博客所提到的论文中的训练数据是KITTI的数据集,因此如果我想要用自己的数据集进行训练的话,就需要先弄清楚KITTI数据集的格式,在以下的网址找到了说明: 首先,数据描述中是这样的: 在以下 ...
- java 给指定时间加上天数or给当前日期加天数
给指定日期加上天数: /** * 指定日期加上天数后的日期 * @param num 为增加的天数 * @param newDate 创建时间 * @return * @throws ParseExc ...
- [转]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/ ...
- sed 引入shell变量
双单引号即可 1.eval sed ’s/$a/$b/’ filename2.sed "s/$a/$b/" filename3.sed ’s/’$a’/’$b’/’ filenam ...
- Android中如何查看内存
文章参照自:http://stackoverflow.com/questions/2298208/how-to-discover-memory-usage-of-my-application-in-a ...
- Issue 0:发刊词
最近读吴军博士的文章,很受感悟.知识的成体系地积累过程对一个人的素养提高很有帮助,所以打算开通这本电子期刊,以一周一篇文章的形式汇总今后的知识体系. 宗旨:及时和团队讨论,反馈:善于利用工具.时间越长 ...
- Java网络编程之流——readline()方法的bug
readline()方法有一个隐含的bug,它不一定会把一个回车看作行的结束.相反,readline()只识别换行或回车/换行对.当在流中检测到回车时,readline()会在继续之前等待,查看下一个 ...
- Jquery 定时器 倒计时
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...