POJ 3498 March of the Penguins(网络最大流)
Description
Somewhere near the south pole, a number of penguins are standing on a number of ice floes. Being social animals, the penguins would like to get together, all on the same floe. The penguins do not want to get wet, so they have use their limited jump distance to get together by jumping from piece to piece. However, temperatures have been high lately, and the floes are showing cracks, and they get damaged further by the force needed to jump to another floe. Fortunately the penguins are real experts on cracking ice floes, and know exactly how many times a penguin can jump off each floe before it disintegrates and disappears. Landing on an ice floe does not damage it. You have to help the penguins find all floes where they can meet.

A sample layout of ice floes with 3 penguins on them.
Input
On the first line one positive number: the number of testcases, at most 100. After that per testcase:
One line with the integer N (1 ≤ N ≤ 100) and a floating-point number D (0 ≤ D ≤ 100 000 ), denoting the number of ice pieces and the maximum distance a penguin can jump.
N lines, each line containing xi, yi, ni and mi, denoting for each ice piece its X and Y coordinate, the number of penguins on it and the maximum number of times a penguin can jump off this piece before it disappears ( −10 000 ≤ xi, yi ≤ 10 000 , 0 ≤ ni ≤ 10, 1 ≤ mi ≤ 200).
Output
Per testcase:
- One line containing a space-separated list of 0-based indices of the pieces on which all penguins can meet. If no such piece exists, output a line with the single number −1.
题目大意:有n块浮冰,每块冰上有ni只企鹅,他们最多能跳距离D,现在这些企鹅想在同一块冰上集中,但是呢,冰有裂缝,每块冰只能被企鹅在上面跳走mi次(跳进来和站在上面都不影响),问企鹅们可以集中在哪些浮冰上。
思路:拆点,每个点x拆成x和x',每个x到x'连边,容量为能跳多少次。然后如果i到j的距离不大于D,那么在i'到j连一条边,容量为无穷大。源点S到每一个点x连一条边,容量为有多少只企鹅在x上。最后,枚举每一个点x,x到汇点T连一条边,容量为无穷大,判断最大流是否等于企鹅的数量。
算法正确性说明:如此建图,每只企鹅都从源点开始走到汇点,但每个冰块只能经过cap[x->x']次,保证了企鹅只能从x跳走mi次。
PS:我枚举的时候,只是把前一条边的容量搞成0(要删掉好像好麻烦的样子),再新建一条从枚举点到汇点的边,这样就不用每次都建图了。
PS2:D居然是浮点数……还好没因此WA……
BFS+ISAP(235MS):
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std; const int MAXN = ;
const int MAXE = MAXN * MAXN * ;
const int INF = 0x3f3f3f3f; struct SAP {
int head[MAXN], dis[MAXN], gap[MAXN], pre[MAXN], cur[MAXN];
int to[MAXE], next[MAXE], flow[MAXE], cap[MAXE];
int st, ed, n, ecnt; void init() {
memset(head, , sizeof(head));
ecnt = ;
} void add_edge(int u, int v, int f) {
to[ecnt] = v; cap[ecnt] = f; flow[ecnt] = ; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; cap[ecnt] = ; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
//printf("%d->%d cap=%d\n", u, v, f);
} void bfs() {
memset(dis, 0x3f, sizeof(dis));
queue<int> que; que.push(ed);
dis[ed] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
++gap[dis[u]];
for(int p = head[u]; p; p = next[p]) {
int v = to[p];
if(dis[v] > n && cap[p ^ ]) {
dis[v] = dis[u] + ;
que.push(v);
}
}
}
} int Maxflow(int ss, int tt, int nn) {
st = ss, ed = tt, n = nn;
int ans = , minFlow = INF, u;
for(int i = ; i <= n; ++i) {
cur[i] = head[i];
gap[i] = ;
}
u = pre[st] = st;
bfs();
while(dis[st] < n) {
bool flag = false;
for(int &p = cur[u]; p; p = next[p]) {
int v = to[p];
if(cap[p] > flow[p] && dis[u] == dis[v] + ) {
flag = true;
minFlow = min(minFlow, cap[p] - flow[p]);
pre[v] = u;
u = v;
if(u == ed) {
ans += minFlow;
while(u != st) {
u = pre[u];
flow[cur[u]] += minFlow;
flow[cur[u] ^ ] -= minFlow;
}
minFlow = INF;
}
break;
}
}
if(flag) continue;
int minDis = n - ;
for(int p = head[u]; p; p = next[p]) {
int v = to[p];
if(cap[p] > flow[p] && dis[v] < minDis) {
minDis = dis[v];
cur[u] = p;
}
}
if(--gap[dis[u]] == ) break;
gap[dis[u] = minDis + ]++;
u = pre[u];
}
return ans;
}
} G; struct Point {
int x, y, n, m;
void read() {
scanf("%d%d%d%d", &x, &y, &n, &m);
}
}; double dist(const Point &a, const Point &b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
} int n, ss, tt;
int ans[], cnt;
double d;
Point p[]; void make_graph() {
ss = * n + , tt = ss + ;
G.init();
for(int i = ; i <= n; ++i)
if(p[i].n) G.add_edge(ss, * i - , p[i].n);
for(int i = ; i <= n; ++i) G.add_edge( * i - , * i, p[i].m);
for(int i = ; i <= n; ++i) {
for(int j = ; j <= n; ++j) {
if(i == j || dist(p[i], p[j]) > d) continue;
G.add_edge(i * , j * - , INF);
}
}
} int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%lf", &n, &d);
for(int i = ; i <= n; ++i) p[i].read();
int sum = ;
for(int i = ; i <= n; ++i) sum += p[i].n;
make_graph();
cnt = ;
for(int i = ; i <= n; ++i) {
G.add_edge(i * - , tt, INF);
memset(G.flow, , sizeof(G.flow));
if(sum == G.Maxflow(ss, tt, tt)) ans[++cnt] = i - ;
G.cap[G.ecnt - ] = ;
}
if(cnt == ) puts("-1");
else {
for(int i = ; i < cnt; ++i) printf("%d ", ans[i]);
printf("%d\n", ans[cnt]);
}
}
}
POJ 3498 March of the Penguins(网络最大流)的更多相关文章
- poj 3498 March of the Penguins(最大流+拆点)
题目大意:在南极生活着一些企鹅,这些企鹅站在一些冰块上,现在要让这些企鹅都跳到同一个冰块上.但是企鹅有最大的跳跃距离,每只企鹅从冰块上跳走时会给冰块造成损害,因此企鹅跳离每个冰块都有次数限制.找出企鹅 ...
- [POJ 3498] March of the Penguins
March of the Penguins Time Limit: 8000MS Memory Limit: 65536K Total Submissions: 4378 Accepted: ...
- poj 3498 March of the Penguins(拆点+枚举汇点 最大流)
March of the Penguins Time Limit: 8000MS Memory Limit: 65536K Total Submissions: 4873 Accepted: ...
- poj 1273 && hdu 1532 Drainage Ditches (网络最大流)
Drainage Ditches Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 53640 Accepted: 2044 ...
- UVALive-3972 March of the Penguins (最大流:节点容量)
题目大意:有n个带有裂缝的冰块.已知每个冰块的坐标和已经站在上面的企鹅数目,每当一个企鹅从一个冰块a跳到另一个冰块b上的时候,冰块a上的裂缝便增大一点,还知道每个冰块上最多能被跳跃的次数.所有的企鹅都 ...
- 【POJ3498】March of the Penguins(最大流,裂点)
题意:在靠近南极的某处,一些企鹅站在许多漂浮的冰块上.由于企鹅是群居动物,所以它们想要聚集到一起,在同一个冰块上.企鹅们不想把自己的身体弄湿,所以它们在冰块之间跳跃,但是它们的跳跃距离,有一个上限. ...
- poj 3498 最大流
March of the Penguins Time Limit: 8000MS Memory Limit: 65536K Total Submissions: 4809 Accepted: ...
- POJ--1087--A Plug for UNIX【Dinic】网络最大流
链接:http://poj.org/problem? id=1087 题意:提供n种插座.每种插座仅仅有一个,有m个设备须要使用插座,告诉你设备名称以及使用的插座类型,有k种转换器.能够把某种插座类型 ...
- P3376 【模板】网络最大流
P3376 [模板]网络最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点 ...
随机推荐
- java web多组件协作实现用户登录验证
实现步骤: 1.创建用户登录提交界面 2.创建处理用户登录请求servlet组件Main 3.创建代表登录成功响应的servlet的组件LoginSuccess 4.创建代表登录失败响应的servle ...
- redhat6 快速部署percona
1.首先得能访问外网 2.yum install http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-relea ...
- Tomcat性能监控
Tomcat性能监控工具很多,这里介绍两种1.JMeter 2.probe,使用这两种工具都需要在tomcat的安装目录/conf/tomcat-users.xml添加 <tomcat-user ...
- Vue解决接口访问跨域问题
随手摘录 Vue解决接口访问跨域问题 1.打开 config -> index.js 2. 找到proxyTable 3.粘贴 如下代码,'https://www.baidu.com'换成要访问 ...
- IOS移动端(H5)alert/confirm提示信息去除url
前几天写移动端项目用alert和confirm进行信息提示,但发现在iOS系统中,每次提示信息上面都会被添加一行URL地址,安卓却没有,经过查找之后,果然不出所料,兼容!!兼容!!!兼容!!! 需要重 ...
- 利用GoAccess分析Nginx访问日志
原文链接:https://blog.csdn.net/yown/article/details/56027112 需求:及时得到线上用户访问日志分析统计结果,以便给开发.测试.运维.运营人员提供决策! ...
- 学习新框架laravel4 第一天(- -! 新公司版本使用的4,所以还要重新学习)
路由使用: //根目录 Route::get('/', function() { return View::make('hello'); }); 自定义模板: /app/views/home/inde ...
- Python安装及简介
Python简介 Python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言 ...
- [POJ3090]Visible Lattice Points(欧拉函数)
答案为3+2*∑φ(i),(i=2 to n) Code #include <cstdio> int T,n,A[1010]; void Init(){ for(int i=2;i< ...
- Java线程和多线程(十二)——线程池基础
Java 线程池管理多个工作线程,其中包含了一个队列,包含着所有等待被执行的任务.开发者可以通过使用ThreadPoolExecutor来在Java中创建线程池. 线程池是Java中多线程的一个重要概 ...