1. 程式人生 > >ZOJ 3862【貪心】【列舉】

ZOJ 3862【貪心】【列舉】

題目連結

題目大意是給定n條直線,2*n個點,通過交換任意直線的端點位置使得它們互不相交,容易想到可以通過按照座標x,y大小排序的規則來交換它們的位置,即可保證所有直線不相交

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 200005;
typedef pair<int, int> P;
struct node
{
	int x, y, id, link;
	node(int _x, int _y,
int _id = 0) { x = _x, y = _y, id = _id; } bool operator<(const node &r) const { return x == r.x && y < r.y || x < r.x; } }; int p[MAXN]; int main() { int T; scanf("%d", &T); while (T--) { int n; scanf("%d", &n); vector<node> v; v.push_back({ -INF
, -INF, 0 }); int x, y; for (int i = 1; i <= 2 * n; ++i) { scanf("%d%d", &x, &y); v.push_back(node(x, y, i)); } for (int i = 1; i <= n; ++i) { scanf("%d%d", &x, &y); v[x].link = y, v[y].link = x; } sort(v.begin(), v.end()); for (int i = 1; i <= 2 * n
; ++i) { p[v[i].id] = i; } vector<P> ans; for (int i = 1; i <= 2 * n; i += 2) { if (v[i].link == v[i + 1].id) continue; ans.push_back({ v[i].link, v[i + 1].id }); int j = p[v[i].link]; v[j].id = v[i + 1].id; v[j].link = v[i + 1].link; p[v[i + 1].id] = j; } printf("%zd\n", ans.size()); for (P i : ans) { printf("%d %d\n", i.first, i.second); } } }