Problem:
Problem E: Earth Observation with a Mobile Robot Team

A new type of mobile robot has been developed for environmental earth
observation.
It moves around on the ground, acquiring and recording various sorts of
observational data using high precision sensors.
Robots of this type have short range wireless communication devices and can
exchange observational data with ones nearby.
They also have large capacity memory units, on which they record data
observed by themselves and those received from others.

Figure 1 illustrates the current positions of three robots A, B, and C and
the geographic coverage of their wireless devices.
Each circle represents the wireless coverage of a robot, with its
center representing the position of the robot.
In this figure, two robots A and B are in the positions where A can
transmit data to B, and vice versa.
In contrast, C cannot communicate with A or B, since it is too remote
from them.
Still, however, once B moves towards C as in Figure 2, B and C can
start communicating with each other.
In this manner, B can relay observational data from A to C.
Figure 3 shows another example, in which data propagate among several robots
instantaneously.

Figure 1: The initial configuration of three robots

Figure 2: Mobile relaying

Figure 3: Instantaneous relaying among multiple robots

As you may notice from these examples, if a team of robots move
properly, observational data quickly spread over a large number of them.
Your mission is to write a program that simulates how information
spreads among robots.
Suppose that, regardless of data size, the time necessary for
communication is negligible.

Input

The input consists of multiple datasets, each in the following format.

N T R

nickname and travel route of the first robot

nickname and travel route of the second robot

...

nickname and travel route of the N-th robot

The first line contains three integers N, T, and
R that are the number of robots, the length of the simulation
period, and the maximum distance wireless signals can reach,
respectively, and satisfy that 1 <=N <= 100, 1 <=
T <= 1000, and 1 <= R <= 10.

The nickname and travel route of each robot are given in the
following format.

nickname

t0 x0 y0

t1 vx1 vy1

t2 vx2 vy2

...

tk vxk vyk

Nickname is a character string of length between one and eight that
only contains lowercase letters.
No two robots in a dataset may have the same nickname.
Each of the lines following nickname contains three integers,
satisfying the following conditions.

0 = t0 < t1 < ... < tk = T

-10 <= vx1, vy1, ..., vxk, vyk<= 10

A robot moves around on a two dimensional plane.
(x0, y0) is the location of the
robot at time 0.
From time ti-1 to ti (0
< i <= k), the velocities in the x and
y directions are vxi and
vyi, respectively.
Therefore, the travel route of a robot is piecewise linear.
Note that it may self-overlap or self-intersect.

You may assume that each dataset satisfies the following conditions.

The distance between any two robots at time 0 is not exactly R.

The x- and y-coordinates
of each robot are always between -500 and 500, inclusive.

Once any robot approaches within R + 10-6 of any
other, the distance between them will become smaller than
R - 10-6 while maintaining the velocities.

Once any robot moves away up to R - 10-6 of any
other, the distance between them will become larger than R
+ 10-6 while maintaining the velocities.

If any pair of robots mutually enter the wireless area of the
opposite ones at time t and any pair, which may share one or
two members with the aforementioned pair, mutually leave the wireless
area of the opposite ones at time t', the difference between
t and t' is no smaller than 10-6 time unit, that is,
|t - t' | >= 10-6.

A dataset may include two or more robots that share the same location
at the same time.
However, you should still consider that they can move with the
designated velocities.

The end of the input is indicated by a line containing three zeros.

Output

For each dataset in the input, your program
should print the nickname of each robot that have got until time
T the observational data originally acquired by the first robot
at time 0.
Each nickname should be written in a separate line in dictionary order
without any superfluous characters such as leading or trailing spaces.

Sample Input

3 5 10
red
0 0 0
5 0 0
green
0 5 5
5 6 1
blue
0 40 5
5 0 0
3 10 5
atom
0 47 32
5 -10 -7
10 1 0
pluto
0 0 0
7 0 0
10 3 3
gesicht
0 25 7
5 -7 -2
10 -1 10
4 100 7
impulse
0 -500 0
100 10 1
freedom
0 -491 0
100 9 2
destiny
0 -472 0
100 7 4
strike
0 -482 0
100 8 3
0 0 0

Output for the Sample Input

blue
green
red
atom
gesicht
pluto
freedom
impulse
strike

Solution in Rust (judge verdict: Accepted)

use std::collections::hash_set::Iter;
use std::rc::Rc;
use std::ops::DivAssign;
use std::ops::MulAssign;
use std::ops::SubAssign;
use std::collections::BinaryHeap;
use std::str::FromStr;
use std::collections::HashSet;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::ops::Neg;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Add;
use std::ops::{AddAssign, Sub};
use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use std::collections::{HashMap, BTreeSet};
use std::cmp::Ordering;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer.trim().to_owned()
}
fn read_lines<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
fn read_tabulate<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split_whitespace().map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
macro_rules! read_map {
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
}
macro_rules! read {
    (mut $ident: ident: String) => {
        let mut $ident = read_value::<String>();
    };
    ($ident: ident: String) => {
        let $ident = read_value::<String>();
    };
    (mut $ident: ident: [$ty:ty]) => {
        let mut $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty]) => {
        let $ident = read_values::<$ty>();
    };
    (mut $ident: ident: [[$ty:ty]; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    ($ident: ident: [[$ty:ty]; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$ty:ty; $size:expr]) => {
        let mut $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$ty:ty; $size:expr]) => {
        let $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    ($($token: tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        read_from_iter!(iter; $($token)*);
    };
}
macro_rules! read_from_iter {
    ($iter:expr; mut $ident:ident:$ty:ty, $($rest:tt)*) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; $ident:ident:$ty:ty, $($rest:tt)*) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; mut $ident:ident:$ty:ty) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter:expr; $ident:ident:$ty:ty) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter: expr; ) => {};
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
}
#[derive(Eq, PartialEq)]
struct Rev<T: Ord>(T);
impl <T: std::cmp::Ord> PartialOrd for Rev<T> {
    fn partial_cmp(&self, rhs: &Rev<T>) -> std::option::Option<std::cmp::Ordering> { 
        rhs.0.partial_cmp(&self.0)
    }
}
impl <T: Ord> Ord for Rev<T> {
    fn cmp(&self, rhs: &Self) -> std::cmp::Ordering { 
        rhs.0.cmp(&self.0)
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
struct Coordinate {
    x: i32, y: i32
}
impl Coordinate {
    fn distance(&self, other: Coordinate) -> f64 {
        (*self - other).length()
    }
}
#[derive(Copy, Clone, Debug)]
struct Vector {
    dx: i32, dy: i32
}
impl Vector {
    fn length(&self) -> f64 {
        ((self.dx * self.dx + self.dy * self.dy) as f64).sqrt()
    }
}
impl Sub for Coordinate {
    type Output = Vector;
    fn sub(self, rhs: Coordinate) -> <Self as std::ops::Sub<Coordinate>>::Output { 
        Vector{dx: self.x - rhs.x, dy: self.y - rhs.y}
    }
}
#[derive(Copy, Clone, Debug)]
struct Robot {
    position: Coordinate, 
    velocity: Vector,
}
impl Robot {
    fn move_ahead(&mut self, time: i32) {
        self.position.x += self.velocity.dx * time;
        self.position.y += self.velocity.dy * time;
    }
    fn change_speed(&mut self, new_velocity: Vector) {
        self.velocity = new_velocity;
    }
    fn connect_time(&self, other: Robot, radius: i32) -> Vec<f64> {
        let dx = (self.position.x - other.position.x) as f64;
        let dy = (self.position.y - other.position.y) as f64;
        let dvx = (self.velocity.dx - other.velocity.dx) as f64;
        let dvy = (self.velocity.dy - other.velocity.dy) as f64;
        QuadraticEquation{a: dvx * dvx + dvy * dvy, b: 2f64 * (dvx * dx + dvy * dy), c: dx * dx + dy * dy - (radius * radius) as f64}.neg_range()
    }
}
fn fmax(a: f64, b: f64) -> f64 {
    if a >= b {
        a
    }else {
        b
    }
}
struct QuadraticEquation {
    a: f64, b: f64, c: f64
}
impl QuadraticEquation {
    fn neg_range(&self) -> Vec<f64> {
        if self.a < 0f64 {
            return QuadraticEquation{a: -self.a, b: -self.b, c: -self.c}.neg_range();
        }else if self.a < 1e-6 && self.b.abs() < 1e-6 {
            return if self.c < 1e-6 { vec![0f64, std::f64::MAX / 2f64] } else { vec![] }
        }else if self.a < 1e-6 {
            return if self.b < 0f64 {vec![fmax(0f64, -self.c / self.b), std::f64::MAX / 2f64]} else if -self.c / self.b >= 0f64 {vec![0f64, -self.c / self.b]} else {vec![]};
        }
        let d = self.b * self.b - 4f64 * self.a * self.c;
        if d < 0f64 {
            return vec![]
        }
        let left = (-self.b - d.sqrt()) / self.a / 2f64;
        let right = (-self.b + d.sqrt()) / self.a / 2f64;
        return if right >= 0f64 {vec![fmax(0f64, left), right]} else {vec![]};
    }
}

enum Event {
    Connect{id1: usize, id2: usize},
    Disconnect{id1: usize, id2: usize},
}
fn main() {
    loop {
        read!(n: usize, last_time: i32, r: i32);
        if n == 0 {break;}
        let mut nicknames = Vec::with_capacity(n);
        let mut robots = Vec::with_capacity(n);
        let mut speed_change = Vec::new();
        for _ in 0 .. n {
            read!(input: String);
            nicknames.push(input);
            read!(_t0 : i32, x: i32, y: i32);
            let mut temp_change = Vec::new();
            loop {
                read!(time: i32, dx: i32, dy: i32);
                temp_change.push((time, Vector{dx: dx, dy: dy}));
                if time == last_time {break;}
            }
            robots.push(Robot{position: Coordinate{x: x, y: y}, velocity: temp_change[0].1});
            for i in 1 .. temp_change.len() {
                speed_change.push(KeyValue{key: temp_change[i - 1].0, value: (robots.len() - 1, temp_change[i].1)});
            }
        }
        speed_change.sort();
        speed_change.push(KeyValue{key: last_time, value: (0, Vector{dx: 0, dy: 0})});
        let mut connection = vec![HashSet::new(); robots.len()];
        let mut has_data = vec![false; robots.len()]; has_data[0] = true;
        let mut events = BinaryHeap::new();
        let mut current_time = 0i32;
        for KeyValue{key: time, value: (id, velocity)} in speed_change {
            for i in 0 .. robots.len() {
                for j in 0 .. i {
                    let connect_time = robots[i].connect_time(robots[j], r);
                    //println!("RobotA: {:?}, RobotB: {:?}, connect: {:?}", robots[j], robots[i], connect_time);
                    if connect_time.len() == 2 {
                        if 0f64 <= connect_time[0] && connect_time[0] + current_time as f64 <= time as f64 {
                            events.push(Rev(KeyValue{value: Event::Connect{id1: i, id2: j}, key: connect_time[0] + current_time as f64}));
                        }
                        if 0f64 <= connect_time[1] && connect_time[1] + current_time as f64 <= time as f64 {
                            events.push(Rev(KeyValue{value: Event::Disconnect{id1: i, id2: j}, key: connect_time[1] + current_time as f64}));
                        }
                    }
                }
            }
            while let Some(Rev(KeyValue{value: event, key: k})) = events.pop() {
                //println!("time: {}", k);
                //println!("coonnect: {:?}", connection);
                match event {
                    Event::Connect{id1: a, id2: b} if !has_data[a] && !has_data[b] => {
                        connection[a].insert(b);
                        connection[b].insert(a);
                    }
                    Event::Connect{id1:a, id2: b} if !has_data[a] || !has_data[b] => {
                        let mut stack = vec![a, b];
                        has_data[a] = true;
                        has_data[b] = true;
                        while let Some(top) = stack.pop() {
                            for &next in &connection[top] {
                                if has_data[next] {continue;}
                                has_data[next] = true;
                                stack.push(next);
                            }
                        }
                    }
                    Event::Disconnect{id1: a, id2: b} if !has_data[a] && !has_data[b] => {
                        connection[a].remove(&b);
                        connection[b].remove(&a);
                    }
                    _ => ()
                }
            }
            for i in 0 .. robots.len() {
                robots[i].move_ahead(time - current_time);
            }
            robots[id].change_speed(velocity);
            current_time = time;
        }
        let mut recieved = (0 .. robots.len()).filter(|&i| has_data[i]).map(|i| nicknames[i].clone()).collect::<Vec<_>>();
        recieved.sort();
        println!("{}", recieved.join("\n"));
    }
}