这道题首先要知道可以讲横纵坐标分开讨论。
这样就转化为区间贪心的问题。
要注意的是要用并查集优化一下。
对左端点排序,然后从右端点找到第一个没有被使用的点。
假设i点的根节点为x,并且x在区间内,就合并:pre[x] = find(x+1)。
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e3+5;
int Case = 1;
int n, m;
struct node{
int l, r, id;
bool operator<(const node x)const{
return r < x.r;
}
}A[maxn], B[maxn];
int res[maxn][2];
int pre[maxn];
int find(int x) {
int t = x;
while(pre[t] != t) t = pre[t];
while(t != x) {
int c = pre[x];
pre[x] = t;
x = c;
}
return t;
}
void init() {
for(int i = 1; i <= n+1; i++) pre[i] = i;
}
void solve() {
for(int i = 1; i <= n; i++) {
int xl, yl, xr, yr;
scanf("%d%d%d%d", &xl, &yl, &xr, &yr);
A[i].l = xl;A[i].r = xr;A[i].id = i;
B[i].l = yl;B[i].r = yr;B[i].id = i;
}
init();
sort(A+1, A+1+n);
sort(B+1, B+1+n);
for(int i = 1; i <= n; i++) {
int x = find(A[i].l);
if(x <= A[i].r) res[A[i].id][0] = x, pre[x] = find(x+1);
else {
printf("IMPOSSIBLE\n");
return;
}
}
init();
for(int i = 1; i <= n; i++) {
int x = find(B[i].l);
if(x <= B[i].r) res[B[i].id][1] = x, pre[x] = find(x+1);
else {
printf("IMPOSSIBLE\n");
return;
}
}
for(int i = 1; i <= n; i++) {
printf("%d %d\n", res[i][0], res[i][1]);
}
return;
}
int main() {
while(scanf("%d", &n) == 1 && n) {
solve();
}
return 0;
}