#![allow(non_snake_case)] fn main(){ let input=Input::new(); let ans=solve(&input); check_output(&input,&ans); for t in &ans{ println!("{} {} {} {}",t.0+1,t.1+1,t.2+1,t.3+1); } } fn solve(input:&Input)->Vec<(usize,usize,usize,usize)>{ let mut low=input.low.clone(); low.sort_by_key(|t|!t.1); let mut g=MaxFlow::new(4*N+2); let s=4*N; let t=s+1; let mut edge=vec![(vec![],vec![]);N]; for i in 0..N{ g.add_edge(s,i,1); g.add_edge(N+i,2*N+i,1); g.add_edge(3*N+i,t,1); for j in 0..N{ if low[i*2+1].1>input.mid[j].1{ let id=g.add_edge(i,j+N,1); edge[j].0.push((id,i*2+1)); } if input.mid[i].1>input.top[j].1{ let id=g.add_edge(i+2*N,j+3*N,1); edge[i].1.push((id,j)); } } } let f=g.solve_with_capacity(s,t,input.K); assert!(f==input.K); let mut ans=vec![]; for i in 0..N{ let Some(&a)=edge[i].0.iter().find(|&t|g.get_flow(t.0)>0) else{continue}; let b=edge[i].1.iter().find(|&t|g.get_flow(t.0)>0).unwrap(); ans.push((i,low[a.1-1].0,low[a.1].0,b.1)); } assert!(ans.len()==input.K); ans } type G=Vec>; const N:usize=500; struct Input{ K:usize, low:Vec<(usize,i64,i64)>, // id,width,height mid:Vec<(usize,i64,i64)>, top:Vec<(usize,i64,i64)>, } impl Input{ fn new()->Input{ let mut scan=Scanner::new(); let n:usize=scan.read(); assert!(n==N); let K:usize=scan.read(); assert!((300..=400).contains(&K)); let mut read_vec=|n|(0..n).map(|_|{ let a:i64=scan.read(); assert!((1..=10000).contains(&a)); a }).collect::>(); let (a,b)=(read_vec(n),read_vec(n)); let (c,d)=(read_vec(2*n),read_vec(2*n)); let (e,f)=(read_vec(n),read_vec(n)); Input{ K, low:(0..2*n).map(|i|(i,c[i],d[i])).collect(), mid:(0..n).map(|i|(i,a[i],b[i])).collect(), top:(0..n).map(|i|(i,e[i],f[i])).collect(), } } } fn check_output(input:&Input,ans:&[(usize,usize,usize,usize)]){ assert!(ans.len()==input.K); let mut cnt=vec![0;N*4]; for &t in ans{ cnt[t.0]+=1; cnt[t.1+N]+=1; cnt[t.2+N]+=1; cnt[t.3+N*3]+=1; } assert!(cnt.iter().all(|&t|t<=1)); for &t in ans{ assert!(input.mid[t.0].1 } impl Scanner{ fn new()->Self{ use std::io::Read; let mut tmp=String::new(); std::io::stdin().read_to_string(&mut tmp).unwrap(); Self{stack:Box::leak(tmp.into_boxed_str()).split_ascii_whitespace()} } fn read(&mut self)->T{ self.stack.next().unwrap().parse::().unwrap_or_else(|_|panic!("parse error {}",std::any::type_name::())) } } type Flow=usize; const INF:Flow=Flow::MAX/4; #[derive(Clone,Copy,Debug,Default)] struct Edge{ rev:usize, cap:Flow, } fn solve_dinic(g:&mut G,s:usize,t:usize)->Flow{ solve_dinic_with_capacity(g,s,t,INF) } fn solve_dinic_with_capacity(g:&mut G,s:usize,t:usize,cap:Flow)->Flow{ struct DFS{ level:Vec, iter:Vec, que:Queue, } impl DFS{ fn bfs(&mut self,g:&G,s:usize,t:usize){ self.level.fill(!0); self.level[s]=0; self.que.clear(); self.que.push_back(s); while let Some(v)=self.que.pop_front(){ for (nv,edge) in g.weight_iter(v){ if edge.cap==0 || self.level[nv]!=!0{ continue; } self.level[nv]=self.level[v]+1; if nv==t{ return; } self.que.push_back(nv); } } } fn dfs(&mut self,g:&mut G,s:usize,v:usize,add:Flow)->usize{ if v==s{ return add; } let mut res=0; let level0=self.level[v]; while self.iter[v],s:usize)->Vec{ let mut seen=vec![false;g.len()]; let mut que=Queue::new(); que.push_back(s); seen[s]=true; while let Some(p)=que.pop_front(){ for (nv,edge) in g.weight_iter(p){ if edge.cap!=0 && !seen[nv]{ seen[nv]=true; que.push_back(nv); } } } seen } struct MaxFlow{ pos:Vec<(usize,usize)>, g:Vec>, } impl MaxFlow{ fn new(n:usize)->Self{ Self{ pos:vec![], g:vec![vec![];n], } } fn add_edge(&mut self,s:usize,t:usize,cap:Flow)->usize{ let id=self.pos.len(); self.pos.push((s,self.g[s].len())); let from_id=self.g[s].len(); let mut to_id=self.g[t].len(); to_id+=(s==t) as usize; self.g[s].push((t,Edge{rev:to_id,cap})); self.g[t].push((s,Edge{rev:from_id,cap:0})); id } fn change_edge(&mut self,id:usize,new_flow:Flow,new_cap:Flow){ assert!(new_flow<=new_cap); let e=&mut self.g[self.pos[id].0][self.pos[id].1]; e.1.cap=new_cap-new_flow; let e=*e; self.g[e.0][e.1.rev].1.cap=new_flow; } fn get_cap(&self,id:usize)->Flow{ let e=self.g[self.pos[id].0][self.pos[id].1]; let re=self.g[e.0][e.1.rev]; e.1.cap+re.1.cap } fn get_flow(&self,id:usize)->Flow{ let e=self.g[self.pos[id].0][self.pos[id].1]; let re=self.g[e.0][e.1.rev]; re.1.cap } fn restore_mincut(&self,s:usize)->Vec{ restore_mincut(&self.g,s) } fn solve(&mut self,s:usize,t:usize)->Flow{ solve_dinic(&mut self.g,s,t) } fn solve_with_capacity(&mut self,s:usize,t:usize,cap:Flow)->Flow{ solve_dinic_with_capacity(&mut self.g,s,t,cap) } } struct Queue{ data:Vec, head:usize, } impl Queue{ fn new()->Self{ Queue{ data:vec![], head:0, } } fn clear(&mut self){ self.data.clear(); self.head=0; } fn is_empty(&self)->bool{ self.head==self.data.len() } fn len(&self)->usize{ self.data.len()-self.head } fn push_back(&mut self,v:T){ self.data.push(v); } fn pop_front(&mut self)->Option where T:Copy{ if self.head==self.data.len(){ None } else{ self.head+=1; Some(self.data[self.head-1]) } } fn front(&self)->Option<&T>{ if self.is_empty(){ None } else{ Some(&self.data[self.head]) } } fn to_slice(&self)->&[T]{ &self.data[self.head..] } } impl std::ops::Deref for Queue{ type Target=[T]; fn deref(&self)->&[T]{ &self.data[self.head..] } } impl std::ops::DerefMut for Queue{ fn deref_mut(&mut self)->&mut [T]{ &mut self.data[self.head..] } } impl std::ops::Index for Queue{ type Output=T; fn index(&self,n:usize)->&T{ let idx=self.head+n; assert!(self.head<=idx); &self.data[idx] } } impl std::ops::IndexMut for Queue{ fn index_mut(&mut self,n:usize)->&mut T{ let idx=self.head+n; assert!(self.head<=idx); &mut self.data[idx] } } trait EdgeIter{ type EdgeIter<'a>:Iterator where Self:'a; fn edge_iter<'a>(&'a self,n:usize)->Self::EdgeIter<'a>; } trait WeightIter:EdgeIter{ type T; type WeightIter<'a>:Iterator where Self:'a; fn weight_iter<'a>(&'a self,n:usize)->Self::WeightIter<'a>; } impl EdgeIter for Vec>{ type EdgeIter<'a>=std::iter::Copied>; fn edge_iter<'a>(&'a self,n:usize)->Self::EdgeIter<'a>{ self[n].iter().copied() } } impl EdgeIter for Vec>{ type EdgeIter<'a>=std::iter::Map,for<'b>fn(&'b(usize,T))->usize> where T:'a; fn edge_iter<'a>(&'a self,n:usize)->Self::EdgeIter<'a>{ self[n].iter().map(|t|t.0) } } impl WeightIter for Vec>{ type T=T; type WeightIter<'a>=std::iter::Copied> where T: 'a; fn weight_iter<'a>(&'a self,n:usize)->Self::WeightIter<'a>{ self[n].iter().copied() } }