#![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>>,
}

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],
		}
	}

	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 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){
	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];
		let dist = input.closest[cur][target];
		for j in 0..dist {
			println!("{}", target+1);
			*count += 1;
			if *count >= input.T {return;}
		}
		cur = target;
	}
}

fn print_route(route: &[usize], input: &Input, count: usize) {
	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);
	}
}

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

// 2-optで巡回経路長を短くする
fn improve_TSP(route: Vec<usize>, input: &Input, cur_step: usize) -> Vec<usize> {
	let mut nroute = route.clone();
	let mut rng = XorShift::new(583290);
	let mut log = vec![0.0;131072];
	let mut count = 0;
	let mut swap = 0;
	let mut rem = 0.0;
	let K = 0.1;
	for i in 0..log.len() {
		log[i] = ((i as f64 + 0.5)/log.len() as f64).log2();
	}
	let start_time = get_time();

	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);
	loop {
		if (count & 127) == 0 {
			let t = get_time()-start_time;
			if t >= tl {break;}
			rem = (tl as f64 - t as f64) * K / tl as f64;
		}
		count += 1;
		if (count & 1) == 0 { // 2-opt
		    let r1 = rng.next(nroute.len()-1);
		    let r2 = rng.next(nroute.len()-1);
		    if r2<=r1+1 {continue;}
		    let s1 = nroute[r1];
		    let s2 = nroute[r1+1];
		    let t1 = nroute[r2];
		    let t2 = nroute[r2+1];
		    // 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 < log[rng.next(log.len())] * rem {
		    	continue;
		    }
		    swap+=1;
		    // eprintln!("{} {}", prev_cost, after_cost);
		    let mut troute = vec![];
		    for i in 0..r1+1 {
		    	troute.push(nroute[i]);
		    }
		    for i in (r1+1..r2+1).rev(){
		    	troute.push(nroute[i]);
		    }
		    for i in r2+1..nroute.len() {
		    	troute.push(nroute[i]);
		    }
		    // eprintln!("prev_dist {} after_dist {}", route_dist(&nroute, &input), route_dist(&troute, &input));
			nroute = troute.clone();
		}
		// else{ // or-opt
		// 	let r1_start = rng.next(nroute.len()-1);
		// 	let r1_end = r1_start + rng.next(3) + 2;
		//     let r2 = rng.next(nroute.len()-1);
		//     if r2 <= r1_end {continue;}
		//     let s1 = nroute[r1_start];
		//     let s2 = nroute[r1_start+1];
		//     let s3 = nroute[r1_end-1];
		//     let s4 = nroute[r1_end];
		//     let t1 = nroute[r2];
		// 	let t2 = nroute[r2+1];
			
		//     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 < log[rng.next(log.len())] * rem {
		//     	continue;
		//     }
		//     swap+=1;
		//     // eprintln!("{} {}", prev_cost, after_cost);
		//     let mut troute = vec![];
		//     for i in 0..r1+1 {
		//     	troute.push(nroute[i]);
		//     }
		//     for i in (r1+1..r2+1).rev(){
		//     	troute.push(nroute[i]);
		//     }
		//     for i in r2+1..nroute.len() {
		//     	troute.push(nroute[i]);
		//     }
		//     // eprintln!("prev_dist {} after_dist {}", route_dist(&nroute, &input), route_dist(&troute, &input));
		// 	nroute = troute.clone();
		// }
	}
	// 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(input: &Input, group_num: usize) -> (Vec<usize>, f64){
	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, &input);
		dist_sum += val;
		eprintln!("group_num {} group_dist {}", group_num, val);
	}
	(ret, dist_sum as f64 / group_num as f64)
}

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..100 {
        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>, input: &Input) -> usize{
	let (mut tmp_dist, tmp_route) = calc_TSP(&set, &input);
	let mut tmp_nroute = improve_TSP(tmp_route, &input, 0);
	route_dist(&tmp_nroute, &input)
}

fn solve(input: &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, mean_dist) = split_nodes(&input, group_num);
	let mut set = vec![HashSet::new(); group_num];
	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 {
			set[group[order.1]].insert(order.1);
		}
		// 行動
		if i!=next_time{
			if i<=wait_time{
				print_stay();
			}
			i += 1;
		}
		else{
			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;}
                // eprintln!("wait");
				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, &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, &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);
				print_route(&last_nroute, &input, i);
				i += 1;
				idx += 1;
				continue;
			}
			print_route(&tmp_nroute, &input, i);
			i += 1;
			set[turn] = HashSet::new();
			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.calc_closest();
	input.dij();
	// input.print_closest();
    solve(&input);
}


Measured memory_bytes: 18664