#![allow(unused_imports)]
#![allow(non_snake_case, unused)]

use std::cmp::*;
use std::collections::*;
use std::ops::*;
use std::fmt;

macro_rules! eprint {
	($($t:tt)*) => {{
		use ::std::io::Write;
		let _ = write!(::std::io::stderr(), $($t)*);
	}};
}
macro_rules! eprintln {
	() => { eprintln!(""); };
	($($t:tt)*) => {{
		use ::std::io::Write;
		let _ = writeln!(::std::io::stderr(), $($t)*);
	}};
}
macro_rules! dbg {
	($v:expr) => {{
		let val = $v;
		eprintln!("[{}:{}] {} = {:?}", file!(), line!(), stringify!($v), val);
		val
	}}
}

macro_rules! mat {
	($($e:expr),*) => { Vec::from(vec![$($e),*]) };
	($($e:expr,)*) => { Vec::from(vec![$($e),*]) };
	($e:expr; $d:expr) => { Vec::from(vec![$e; $d]) };
	($e:expr; $d:expr $(; $ds:expr)+) => { Vec::from(vec![mat![$e $(; $ds)*]; $d]) };
}

macro_rules! ok {
	($a:ident$([$i:expr])*.$f:ident()$(@$t:ident)*) => {
		$a$([$i])*.$f($($t),*)
	};
	($a:ident$([$i:expr])*.$f:ident($e:expr$(,$es:expr)*)$(@$t:ident)*) => { {
		let t = $e;
		ok!($a$([$i])*.$f($($es),*)$(@$t)*@t)
	} };
}

pub fn readln() -> String {
	let mut line = String::new();
	::std::io::stdin().read_line(&mut line).unwrap_or_else(|e| panic!("{}", e));
	line
}

macro_rules! read {
	($($t:tt),*; $n:expr) => {{
		let stdin = ::std::io::stdin();
		let ret = ::std::io::BufRead::lines(stdin.lock()).take($n).map(|line| {
			let line = line.unwrap();
			let mut it = line.split_whitespace();
			_read!(it; $($t),*)
		}).collect::<Vec<_>>();
		ret
	}};
	($($t:tt),*) => {{
		let line = readln();
		let mut it = line.split_whitespace();
		_read!(it; $($t),*)
	}};
}

macro_rules! _read {
	($it:ident; [char]) => {
		_read!($it; String).chars().collect::<Vec<_>>()
	};
	($it:ident; [u8]) => {
		Vec::from(_read!($it; String).into_bytes())
	};
	($it:ident; usize1) => {
		$it.next().unwrap_or_else(|| panic!("input mismatch")).parse::<usize>().unwrap_or_else(|e| panic!("{}", e)) - 1
	};
	($it:ident; [usize1]) => {
		$it.map(|s| s.parse::<usize>().unwrap_or_else(|e| panic!("{}", e)) - 1).collect::<Vec<_>>()
	};
	($it:ident; [$t:ty]) => {
		$it.map(|s| s.parse::<$t>().unwrap_or_else(|e| panic!("{}", e))).collect::<Vec<_>>()
	};
	($it:ident; $t:ty) => {
		$it.next().unwrap_or_else(|| panic!("input mismatch")).parse::<$t>().unwrap_or_else(|e| panic!("{}", e))
	};
	($it:ident; $($t:tt),+) => {
		($(_read!($it; $t)),*)
	};
}

pub fn main() {
	let _ = ::std::thread::Builder::new().name("run".to_string()).stack_size(32 * 1024 * 1024).spawn(run).unwrap().join();
}

const TIME_LIMIT: f64 = 28.0;
const MOD: u32 = 1_000_000_007;

fn get_time() -> f64 {
	static mut STIME: f64 = -1.0;
	let t = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap();
	let ms = t.as_secs() as f64 + t.subsec_nanos() as f64 * 1e-9;
	unsafe {
		if STIME < 0.0 {
			STIME = ms;
		}
		ms - STIME
	}
}

pub struct XorShift {
	pub x: [u32; 4]
}

impl XorShift {
	pub fn new(mut seed: u32) -> XorShift {
		let mut x = [0; 4];
		for i in 0..4 {
			seed = 1812433253u32.wrapping_mul(seed ^ (seed >> 30)).wrapping_add(i as u32);
			x[i] = seed;
		}
		XorShift { x: x }
	}
	pub fn next32(&mut self) -> usize {
		let t = self.x[0] ^ (self.x[0] << 11);
		for i in 0..3 { self.x[i] = self.x[i + 1] }
		self.x[3] = self.x[3] ^ (self.x[3] >> 19) ^ t ^ (t >> 8);
		self.x[3] as usize
	}
	/// [0, n)
	pub fn next(&mut self, n: usize) -> usize {
		loop {
			let t = self.next32();
			let r = t % n;
			if (t - r).checked_add(n).is_some() {
				return r;
			}
		}
	}
}

struct Input {
	V: usize,
	E: usize,
	T: usize,
	edge: Vec<Vec<(usize,usize)>>,
	order: Vec<(usize,usize)>,
	closest: Vec<Vec<usize>>,
	dist: Vec<Vec<i64>>,
	prev: Vec<Vec<usize>>,
	log: Vec<f64>,
	rng: XorShift,
}

impl Input {
	fn new(V: usize, E: usize, T: usize, edge: Vec<Vec<(usize,usize)>>, order: Vec<(usize,usize)>) -> Self {
		Input {
			V: V,
			E: E,
			T: T,
			edge: edge,
			order: order,
			closest: vec![vec![1000000000;V];V],
			dist: vec![vec![]; V],
			prev: vec![vec![]; V],
			log: vec![0.0;131072],
			rng: XorShift::new(583290),
		}
	}

	fn init(&mut self){
		self.calc_closest();
		self.dij();
		self.init_log();
	}

	fn calc_closest(&mut self) {
		let mut g = vec![vec![1000000000;self.V];self.V];
		for i in 0..self.V{
			g[i][i] = 0;
		}
		for i in 0..self.V {
			for &e in &self.edge[i] {
				let s = i;
				let t = e.0;
				let d = e.1;
				g[s][t] = d;
				g[t][s] = d;
			}
		}
		for k in 0..self.V {
			for i in 0..self.V {
				for j in 0..self.V {
					g[i][j] = std::cmp::min(g[i][j], g[i][k] + g[k][j]);
				}
			}
		}
		self.closest = g;
	}

	fn dij(&mut self) {
		for i in 0..self.V{
			let (dist, prev) = dijkstra(i, &self.edge);
			self.dist[i] = dist;
			self.prev[i] = prev;
		}
	}

	fn print_closest(&self) {
		for i in 0..self.V {
			for j in 0..self.V {
				eprint!("{} ", self.closest[i][j]);
			}
			eprintln!();
		}
	}

	fn init_log(&mut self){
		for i in 0..self.log.len() {
			self.log[i] = ((i as f64 + 0.5)/self.log.len() as f64).log2();
		}
	}
}

fn find_closest(cur: usize, list: &[usize], input: &Input) -> (usize, usize){
	let mut ret = 1000000000;
	let mut idx = input.V;
	for &i in list{
		let dist = input.closest[cur][i];
		if dist < ret {
			ret = dist;
			idx = i;
		}
	}
	(idx, ret)
}

// 適当に巡回路を見つける
fn calc_TSP(v: &HashSet<usize>, input: &Input) -> (usize, Vec<usize>) {
	let mut cur = 0;
    let mut list = vec![];
	let mut route = vec![];
	// 先頭に店を追加
	route.push(cur);
    for &i in v.iter() {
        list.push(i);
    }
    let mut dist = 0;
    for i in 0..input.V {
        if list.len()==0 {break;}
        let (idx, ret) = find_closest(cur, &list, &input);
        dist += ret;
        cur = idx;
		route.push(cur);
        let mut nlist = vec![];
        for &j in &list {
            if j==cur {continue;}
            nlist.push(j);
        }
        list = nlist;
    }
	dist += find_closest(cur, &[0], &input).1;
	route.push(0);
    // println!("{}", dist);
	(dist, route)
}

fn dijkstra(start: usize, edge: &Vec<Vec<(usize,usize)>>) -> (Vec<i64>, Vec<usize>){
    let n = edge.len() as usize;
    let mut dist = vec![1000000000 as i64;n]; //初期値は最大距離
    dist[start] = 0;
	let mut prev = vec![n;n];
    let mut heap = BinaryHeap::new();
    heap.push((0, start));
    while let Some((pop_cost, v)) = heap.pop() {
        let cur_cost = -pop_cost;
        if dist[v] < cur_cost {continue;} //これがないと遅い
        for &(next, cost) in edge[v].iter(){
            let next_cost = cur_cost + cost as i64;
			if dist[next] > next_cost {
				dist[next] = next_cost;
				prev[next] = v;
				heap.push((-next_cost, next));
			}
        }
    }
    (dist, prev)
}

fn print_path(s: usize, t: usize, input: &Input, count: &mut usize, delevered: &mut [bool]){
	if *count >= input.T {return;}
	let dist = input.dist[s].clone();
	let prev = input.prev[s].clone();
	let mut list = VecDeque::new();
	let mut cur = t;
	list.push_front(cur);
	loop {
		let target = prev[cur];
		list.push_front(target);
		if target==s {break;}
		cur = target;
	}
	cur = s;
	for i in 1..list.len() {
		let target = list[i];
		delevered[target] = true;
		let dist = input.closest[cur][target];
		for j in 0..dist {
			println!("{}", target+1);
			*count += 1;
			if *count >= input.T {return;}
		}
		cur = target;
	}
}

fn delever_items(route: &[usize], input: &Input, count: usize, mut delevered: &mut [bool]) {
	let mut c = count;
	for i in 0..route.len()-1 {
		let source = route[i];
		let target = route[i+1];
		print_path(source, target, &input, &mut c, &mut delevered);
	}
}

fn print_stay() {
	println!("{}", -1);
}

// Rustのバージョン的にrotate_left()が使えない
// アップデートに期待
pub trait Rotate {
	fn rotate_left(&mut self, len: usize);
}
impl Rotate for [usize]{
	fn rotate_left(&mut self, len: usize) {
		let SL = self.len();
		let mut saved_vec = vec![0;len];
		saved_vec.copy_from_slice(&self[0..len]);
		for i in 0..SL {
			let a = i;
			let b = i+len;
			if b>SL-1 {break;}
			self[a] = self[b];
		}
		self[SL-len..SL].copy_from_slice(&saved_vec);
	}
}

fn print_route_idx(route: &[usize], idx: &[usize]) {
	for &i in idx {
		eprint!("{}: {} ", i, route[i]);
	}
	eprintln!();
}

// 2-optで巡回経路長を短くする
fn improve_TSP(route: Vec<usize>, mut input: &mut Input, cur_step: usize) -> Vec<usize> {
	let mut nroute = route.clone();
	let mut count = 0;
	let mut swap = 0;
	let mut rem = 0.0;
	let K = 0.1;
	let start_time = get_time();
	let ROUTE_LEN = route.len();
	let LOG_LEN = input.log.len();

	let mut tl = TIME_LIMIT * cur_step as f64 / input.T as f64 - start_time;
	if cur_step <= 8000 && tl<=TIME_LIMIT/75.0 {tl=TIME_LIMIT/75.0;}
	if cur_step==0 {tl=TIME_LIMIT/500.0;}
	if cur_step >= 9500 && tl<=0.0 {tl=0.7;}
	eprintln!("tl {}", tl);
	let mut t = get_time()-start_time;
	loop {
		if (count & 127) == 0 {
			t = get_time()-start_time;
			if t >= tl {break;}
			rem = (tl as f64 - t as f64) * K / tl as f64;
		}
		count += 1;
		if count%5 == 0 { // 2-opt
		    let s1_idx = input.rng.next(ROUTE_LEN-1);
		    let t1_idx = input.rng.next(ROUTE_LEN-1);
			if t1_idx<=s1_idx+1 {continue;}
			
			// s1->s2...t1->t2
		    let s1 = nroute[s1_idx];
		    let s2 = nroute[s1_idx+1];
		    let t1 = nroute[t1_idx];
			let t2 = nroute[t1_idx+1];
			if s1==0 && t2==0 {continue;} // この場合、経路が逆順になるだけなので無視
		    // println!("{} {} {} {}", s1, s2, t1, t2);
		    let prev_cost = input.closest[s1][s2] + input.closest[t1][t2];
		    let after_cost = input.closest[s1][t1] + input.closest[s2][t2];
		    let gain = (prev_cost as f64 - after_cost as f64)/ prev_cost as f64;
		    if gain < input.log[input.rng.next(LOG_LEN)] * rem {
		    	continue;
		    }
		    swap+=1;
		    // if true {
			// 	eprint!("2-opt {} {} ", prev_cost, after_cost);
			// 	eprintln!("s1 {} s2 {} t1 {} t2 {}", s1, s2, t1, t2);
			// }
			
			// s1->s2...t1->t2
			nroute[s1_idx+1..t1_idx+1].reverse(); // s1->t1...s2->t2
		}
		else{ // 3-opt
			if ROUTE_LEN<6 {continue;}
			let s1_idx = input.rng.next(ROUTE_LEN-5);
			let s2_idx = s1_idx + 1;
		    let t1_idx = input.rng.next(ROUTE_LEN-3);
			let t2_idx = t1_idx + 1;
			let u1_idx = input.rng.next(ROUTE_LEN-1);
			let u2_idx = u1_idx + 1;
			if t1_idx <= s2_idx {continue;}
			if u1_idx <= t2_idx {continue;}
			
			// s1->s2...t1->t2...u1->u2  
		    let s1 = nroute[s1_idx];
		    let s2 = nroute[s2_idx];
		    let t1 = nroute[t1_idx];
		    let t2 = nroute[t2_idx];
		    let u1 = nroute[u1_idx];
			let u2 = nroute[u2_idx];
			
			let mut prev_cost = 0;
			prev_cost += input.closest[s1][s2];
			prev_cost += input.closest[t1][t2];
			prev_cost += input.closest[u1][u2];

			let mut after_cost = 0;
			if count%5==1{
				// s1->t1...s2->u1...t2->u2
				after_cost += input.closest[s1][t1];
				after_cost += input.closest[s2][u1];
				after_cost += input.closest[t2][u2];
				let gain = (prev_cost as f64 - after_cost as f64)/ prev_cost as f64;
				if gain < input.log[input.rng.next(LOG_LEN)] * rem {
					continue;
				}
				
				swap+=1;
				// s1->s2...t1->t2...u1->u2
				nroute[s2_idx..t1_idx+1].reverse(); // s1->t1...s2->t2...u1->u2
				nroute[t2_idx..u1_idx+1].reverse(); // s1->t1...s2->u1...t2->u2
			}
			if count%5==2{
				// s1->t2...u1->s2...t1->u2
				after_cost += input.closest[s1][t2];
				after_cost += input.closest[u1][s2];
				after_cost += input.closest[t1][u2];
				let gain = (prev_cost as f64 - after_cost as f64)/ prev_cost as f64;
				if gain < input.log[input.rng.next(LOG_LEN)] * rem {
					continue;
				}
				
				swap+=1;
				// s1->s2...t1->t2...u1->u2
				nroute[s2_idx..u1_idx+1].rotate_left(t1_idx-s2_idx+1); // s1->t2...u1->s2...t1->u2
			}
			// if count%5==3{
			// 	// s1->t2...u1->t1...s2->u2
			// 	after_cost += input.closest[s1][t1];
			// 	after_cost += input.closest[t1][u1];
			// 	after_cost += input.closest[s2][u2];
			// 	let gain = (prev_cost as f64 - after_cost as f64)/ prev_cost as f64;
			// 	if gain < input.log[input.rng.next(LOG_LEN)] * rem {
			// 		continue;
			// 	}
				
			// 	swap+=1;
			// 	// s1->s2...t1->t2...u1->u2
			// 	nroute[s2_idx..u1_idx+1].rotate_left(t1_idx-s2_idx);  // s1->t1->t2...u1->s2...u2
			// 	nroute[t1_idx+1..t1_idx+1+(u1_idx-t2_idx)].reverse(); // s1->t1->u1...t2->s2...u2
			// 	nroute[u2_idx-1-(t1_idx-s2_idx-1)..u2_idx].reverse(); // s1->t1->u1...t2...s2->u2
			// }
		}
	}
	eprintln!("swap {}", swap);
	nroute
}

fn route_dist(route: &[usize], input: &Input) -> usize {
	let mut res = 0;
	for i in 0..route.len()-1 {
		let source = route[i];
		let target = route[i+1];
		res += input.closest[source][target];
	}
	res
}

fn split_nodes(mut input: &mut Input, group_num: usize) -> Vec<usize>{
	let mut ret = vec![0; input.V];
    ret = k_means(&input, group_num);
    let mut dist_sum = 0;
    for i in 0..group_num {
		let mut set = HashSet::new();
		for j in 1..input.V {
			if ret[j]==i {
				set.insert(j);
			}
		}
		// let val = calc_optimal_route_dist(&set, &mut input);
		// dist_sum += val;
		// eprintln!("group_num {} group_dist {}", group_num, val);
	}
	ret
}

fn k_means(input: &Input, group_num: usize) -> Vec<usize>{
    let mut center = vec![0;group_num];
    // 適当に中心を決める
    for i in 0..group_num {
        center[i] = input.V/group_num * i;
    }
    let mut ret = vec![];
    for l in 0..50 {
        let mut group = vec![0;input.V];
        // 各頂点を、一番近い中心のグループに分類
        for i in 0..input.V {
            let mut min_dist = 1000000000;
            for j in 0..group_num {
                let dist = input.closest[i][center[j]];
                if dist<=min_dist {
                    min_dist = dist;
                    group[i] = j;
                }
            }
        }
        let mut set = vec![vec![];group_num];
        for i in 0..input.V {
            set[group[i]].push(i);
        }
        // 各グループの中心を決める
        // グループ内の頂点に対する最短距離の最大値が最も小さいものを中心とする
        for i in 0..group_num {
            let mut base = 1000000000;
            for &s in &set[i] {
                let mut max_dist = 0;
                for &t in &set[i]{
                    let dist = input.closest[s][t];
                    max_dist = max(max_dist, dist);
                }
                if max_dist < base {
                    base = max_dist;
                    center[i] = s;
                }
            }
        }
        ret = group;
        // for i in 0..group_num {
        //     eprint!("center {} ", center[i]);
        // }
        // eprintln!();
    }
    let mut item_num = vec![0;group_num];
    for i in 0..input.V {
        item_num[ret[i]] += 1;
    }
    for i in 0..group_num {
        eprintln!("item_num {}", item_num[i]);
    }

    ret
}

fn calc_optimal_route_dist(set: &HashSet<usize>, mut input: &mut Input) -> usize{
	let (mut tmp_dist, tmp_route) = calc_TSP(&set, &input);
	let mut tmp_nroute = improve_TSP(tmp_route, &mut input, 0);
	route_dist(&tmp_nroute, &input)
}

fn solve(mut input: &mut Input){
	let ITEM_STEP = 10;
	let mut next_time = ITEM_STEP;
	let mut sum = 0;
	let mut wait_time = next_time;
	let mut group_num = 3;
	let group = split_nodes(&mut input, group_num);
	let mut delevered = vec![true;input.V];
	let mut idx = 0;
	let mut i = 0;
	let mut diff = input.T;
	let mut turn = 0;
	loop {
		if i>=input.T {break;}
		// 行動決定前に注文が入る
		let order = input.order[i];
		if order.1 != input.V {
			delevered[order.1] = false;
		}
		// 行動
		if i!=next_time{
			if i<=wait_time{
				print_stay();
			}
			i += 1;
		}
		else{
			let mut set = vec![HashSet::new(); group_num];
			// 未配達の品物に関して、グループを作成
			for j in 1..input.V {
				if !delevered[j]{
					set[group[j]].insert(j);
				}
			}
			if set[turn].len()==0 || (set[turn].len()<=2 && i<9500) { // 注文がほぼないときは処理をしない
				next_time = i + ITEM_STEP;
				wait_time = i + ITEM_STEP;
                if i>= 9500 {turn = (turn+1)%group_num;}
				continue;
			}
			let (prev_dist, tmp_route) = calc_TSP(&set[turn], &input);
			let mut tmp_nroute = vec![];
			if set[turn].len()>2 {tmp_nroute = improve_TSP(tmp_route, &mut input, i);}
			else {tmp_nroute = tmp_route;}
			let after_dist = route_dist(&tmp_nroute, &input);
			next_time = i + after_dist;
			eprintln!("step {} size {} turn {} prev_dist {} after_dist {}", i, set[turn].len(), turn, prev_dist, after_dist);
			// 最後はまとめられる分をまとめて配送
			if i > 9500 && next_time < input.T{
				let mut last_num = 1;
				let mut last_set = HashSet::new();
				for &j in &set[turn]{
					last_set.insert(j);
				}
				set[turn] = HashSet::new();
				for j in turn+1..turn+group_num {
					let next_turn = j%group_num;
					if set[next_turn].len() > 0 {last_num+=1;}
					for &k in &set[next_turn]{
						last_set.insert(k);
					}
					set[next_turn] = HashSet::new();
					let (next_dist, next_route) = calc_TSP(&last_set, &input);
					let next_limit = i + next_dist;
					if next_limit>=input.T+100 {break;}
				}
				let (mut last_prev_dist, last_route) = calc_TSP(&last_set, &input);
				let mut last_nroute = vec![];
				if last_set.len() > 2 {last_nroute = improve_TSP(last_route, &mut input, i);}
				else {last_nroute = last_route;}
				let last_after_dist = route_dist(&last_nroute, &input);
				next_time = i + last_after_dist;
				eprintln!("step {} size {} num {} last_prev_dist {} last_after_dist {}", i, last_set.len(), last_num, last_prev_dist, last_after_dist);
				delever_items(&last_nroute, &input, i, &mut delevered);
				i += 1;
				idx += 1;
				continue;
			}
			delever_items(&tmp_nroute, &input, i, &mut delevered);
			i += 1;
			turn = (turn+1)%group_num;
			idx += 1;
		}
	}
	let order_num = input.order.iter().filter(|x| x.1!=input.V).collect::<Vec<&(usize,usize)>>().len();
	eprintln!("V {} E {}", input.V, input.E);
	eprintln!("idx {} order {}", idx, order_num);
    eprintln!("next_time {}", next_time);
}

fn read_inputs() -> Input {
	let (V,E) = read!(usize,usize);
	let uvd = read!([usize];E);
	let T = read!(usize);
	let mut order = vec![(V,V);T];
	for i in 0..T {
		let N = read!(usize);
		if N==0 {continue;}
		let info = read!(usize,usize);
		order[i] = (info.0-1, info.1-1);
	}
	let mut edge = vec![vec![];V];
	for i in 0..E {
		let s = uvd[i][0]-1;
		let t = uvd[i][1]-1;
		let d = uvd[i][2];
		edge[s].push((t,d));
		edge[t].push((s,d));
	}
	let input = Input::new(V,E,T,edge,order);
	input
}

fn run() {
	let mut input = read_inputs();
	input.init();
	// input.print_closest();
    solve(&mut input);
}


Measured memory_bytes: 12668