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 xiyini 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 ≤ xiyi ≤ 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(网络最大流)的更多相关文章

  1. poj 3498 March of the Penguins(最大流+拆点)

    题目大意:在南极生活着一些企鹅,这些企鹅站在一些冰块上,现在要让这些企鹅都跳到同一个冰块上.但是企鹅有最大的跳跃距离,每只企鹅从冰块上跳走时会给冰块造成损害,因此企鹅跳离每个冰块都有次数限制.找出企鹅 ...

  2. [POJ 3498] March of the Penguins

    March of the Penguins Time Limit: 8000MS   Memory Limit: 65536K Total Submissions: 4378   Accepted:  ...

  3. poj 3498 March of the Penguins(拆点+枚举汇点 最大流)

    March of the Penguins Time Limit: 8000MS   Memory Limit: 65536K Total Submissions: 4873   Accepted: ...

  4. poj 1273 && hdu 1532 Drainage Ditches (网络最大流)

    Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 53640   Accepted: 2044 ...

  5. UVALive-3972 March of the Penguins (最大流:节点容量)

    题目大意:有n个带有裂缝的冰块.已知每个冰块的坐标和已经站在上面的企鹅数目,每当一个企鹅从一个冰块a跳到另一个冰块b上的时候,冰块a上的裂缝便增大一点,还知道每个冰块上最多能被跳跃的次数.所有的企鹅都 ...

  6. 【POJ3498】March of the Penguins(最大流,裂点)

    题意:在靠近南极的某处,一些企鹅站在许多漂浮的冰块上.由于企鹅是群居动物,所以它们想要聚集到一起,在同一个冰块上.企鹅们不想把自己的身体弄湿,所以它们在冰块之间跳跃,但是它们的跳跃距离,有一个上限.  ...

  7. poj 3498 最大流

    March of the Penguins Time Limit: 8000MS   Memory Limit: 65536K Total Submissions: 4809   Accepted:  ...

  8. POJ--1087--A Plug for UNIX【Dinic】网络最大流

    链接:http://poj.org/problem? id=1087 题意:提供n种插座.每种插座仅仅有一个,有m个设备须要使用插座,告诉你设备名称以及使用的插座类型,有k种转换器.能够把某种插座类型 ...

  9. P3376 【模板】网络最大流

    P3376 [模板]网络最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点 ...

随机推荐

  1. HTTP学习之URL与资源

    URL是因特网资源的标准化名称,该字符串指向一条电子信息片段,定义服务端应用程序在什么位置以及客户端要如何与其交互 一条完整的URL由多个片段组成. 通用URL组件 方案 以哪种协议访问服务器 用户 ...

  2. rails应用中各数据平台的对接

    1.mongo #Gemfile添加如下两个gem包gem 'mongoid', '~> 5.1.0' gem 'mongo', '~> 2.4’ @client = Mongo::Cli ...

  3. Leecode刷题之旅-C语言/python-203移除链表元素

    /* * @lc app=leetcode.cn id=203 lang=c * * [203] 移除链表元素 * * https://leetcode-cn.com/problems/remove- ...

  4. Go 入门 - 控制流

    主要内容来自中文版的官方教程Go语言之旅 目的为总结要点 循环 Go 只有 for循环 for 由三部分组成,用分号间隔开 初始化语句:在第一次迭代之前执行,通常为一句短变量声明(i:=0) 条件表达 ...

  5. ERROR oslo_service.service PlacementNotConfigured 解决办法

    PlacementNotConfigured: This compute is not configured to talk to the placement service 原因:官方文档中遗漏了- ...

  6. 洛谷九月月赛T1 思考

    很迷的一道题目,刚开始直接枚举n个1,然后去mod m ,爆0,后来发现一个神奇性质:找到递推公式An=An-1*10+1,枚举n,不断mod m,每递推一次就1的个数加一.居然可行! 听说余数具有可 ...

  7. 北京Uber优步司机奖励政策(1月27日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  8. 成都Uber优步司机奖励政策(8月31日~9月6日)

    本周(8月31日-9月6日),优步成都继续推出丰厚保底奖励,日保底总金额最高575元,每周保底最高可获得3595元.优步还加大了乘客端折扣力度,最低五折坐车!单子超多,上线就有单,接单接不停!欢迎各位 ...

  9. 天津Uber优步司机奖励政策(1月11日~1月17日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  10. stm32 nucleo系列开发板的接口

    1. 首先说的是 Arduino接口,所有的nucleo系列都支持这个接口,而且像F767这种尺寸长的板子也有的,不过是双排排针,其实就是外侧也是 Arduino接口 2. 板子接上电脑之后有个串口