hdu2732 网络流经典建图
来源:互联网 发布:java游戏设计吃豆豆 编辑:程序博客网 时间:2024/05/16 20:47
http://acm.hdu.edu.cn/showproblem.php?pid=2732
题目大意:
给了n和d,表示有n行的图,(列数没给),对于每一个人都可以最长跳d的距离,对于每一个柱子有一个限定条件,只能从这里跳出去多少次。给了两张图,一张表示柱子的限定条件,一张给了现在那些柱子上有人。问有几个人不能跳到图的外面。
思路:
最大流建图。将图的外面抽象为一个汇点t,对于图中本来就可以跳出去的点,就可以连一条边到t了。对于可以跳到图中别的点的,就可以从这个点连一条边过去。比较直观的想法就是这些边的容量都设为这个柱子限定的次数,最后跑最大流就好了。但是如果这个柱子可以跳到旁边很多的点上,每一个边的容量都是这个限定次数的话,等于限定的次数被放大了。那么就考虑拆点,将每个点拆成点1,点2,1->2连一条边容量为限定的次数。对于能跳到别的边,就从2连一条边到外面的点,容量为INF。
步骤:
拆点
1.将能够直接跳出去的点,拆出的第一个点连到t,容量为限定的次数。
2.不能直接跳出去的,将点1连到点2,容量为限定的次数。
3.对于能跳到别的点的,将这个点2连到别的点的点1,容量为INF。
4.对于柱子上有人的,从s连一条边到该点的点1,容量为1。
跑最大流。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <stack>#include <vector>using namespace std;#define M 1009typedef struct edge{ int to,cap,rev;};vector<edge> G[M];char mp1[30][30],mp2[30][30];int level[M],iter[M];int n,m,d;int T;int s,t,sum;const int INF = 0x3f3f3f3f;void init(){ for(int i = 0;i <= 2*n*m+2;i++) G[i].clear(); sum = 0;}int to1(int i,int j){ return i*m + j+1;}int to2(int i,int j){ return to1(i,j) + n*m;}int dis(int x1,int x2,int y1,int y2){ return abs(x1-x2) + abs(y1-y2);}void add_edge(int u,int v,int cap){ G[u].push_back(edge{v,cap,G[v].size()}); G[v].push_back(edge{u,0,G[u].size()-1});}void bfs(int s){ memset(level,-1,sizeof(level)); level[s] = 0; queue<int> q; q.push(s); while(!q.empty()) { int v = q.front(); q.pop(); for(int i = 0;i < G[v].size();i++) { edge& e = G[v][i]; if(e.cap > 0 && level[e.to] < 0) { level[e.to] = level[v] + 1; q.push(e.to); } } }}int dfs(int u,int t,int f){ if(u == t) return f; for(int& i = iter[u];i < G[u].size();i++) { edge& e = G[u][i]; if(e.cap > 0 && level[e.to] > level[u]) { int d = dfs(e.to,t,min(f,e.cap)); if(d > 0) { e.cap -= d; G[e.to][e.rev].cap += d; return d; } } } return 0;}int max_flow(){ int flow = 0; for(;;) { bfs(s); memset(iter,0,sizeof(iter)); if(level[t] < 0) return flow; int f = 0; while((f = dfs(s,t,INF)) > 0) flow += f; }}int main(){ scanf("%d",&T); int k = 0; while(k < T) { init(); k++; scanf("%d %d",&n,&d); for(int i = 0;i < n;i++) scanf("%s",mp1[i]); m = strlen(mp1[0]); for(int i = 0;i < n;i++) scanf("%s",mp2[i]); s = 0; t = 2*n*m+1; for(int i = 0;i < n;i++) { for(int j = 0;j < m;j++) { if(mp1[i][j] - '0' > 0) { //add_edge(to1(i,j),to2(i,j),mp1[i][j]-'0'); if(i+1 <= d || j+1 <= d || n-i <= d || m-j <= d) { add_edge(to1(i,j),t,mp1[i][j]-'0'); continue; } else add_edge(to1(i,j),to2(i,j),mp1[i][j]-'0'); for(int ii = -d;ii <= d;ii++) { for(int jj = -d;jj <= d;jj++) { int x = i + ii; int y = j + jj; if(x == i && y == j) continue; if(x < 0 || y < 0 || x >= n || y >= m || dis(i,x,j,y) > d || mp1[x][y]-'0' == 0) continue; add_edge(to2(i,j),to1(x,y),INF); } } } } } for(int i = 0;i < n;i++) { for(int j = 0;j < m;j++) { if(mp2[i][j] == 'L') { add_edge(s,to1(i,j),1); sum++; } } } int flow = max_flow(); int ans = sum - flow; printf("Case #%d: ",k); if(ans > 1) printf("%d lizards were left behind.\n",ans); else if (ans == 1) printf("1 lizard was left behind.\n"); else if (ans == 0) printf("no lizard was left behind.\n"); } return 0;}
0 0
- hdu2732 网络流经典建图
- hdu2732,网络流
- 【 zoj 3348 】Schedule 【网络流经典建图】
- poj 1149 PIGS【网络流经典建图】
- 【网络流】hdu2732 Leapin' Lizards
- poj1459 网络流经典
- [总结] 网络流经典建模
- 网络流。。。。经典模型。。。HDU2732 && PKU 2711
- POJ1459 多源多汇网络流经典模型
- POJ 1149:PIGS 网络流经典题
- UVA - 1658(网络流经典拆点方法)
- POJ 1149 PIGS(网络流经典建图题)
- POJ1149 最大流经典建图PIG
- poj 1149 最大流经典建图
- 网络流 HDU2732 && PKU 2711 最大流 SAP
- POJ 3281【拆点 && 最大流经典建图】
- poj--1149--PIGS(最大流经典建图)
- 网络封包程序,可以截获流经网卡的所有数据包
- RStudio Linux Server 版本 安装配置 说明
- ios8新特性widget开发
- centos 中文字体解决方案
- 开始记录生活
- 页面禁止用户输入中文实现方式
- hdu2732 网络流经典建图
- Java IO
- hadoop平台搭建详解
- mfc 按钮快捷键
- 【LeetCode】226. Invert Binary Tree 二叉树翻转
- NYOJ 整数划分
- 深入理解 Java中的 流 (Stream)
- IOS:Objective-C中奇特的方法声明语法理解
- maven使用积累