제출 #543367

#제출 시각아이디문제언어결과실행 시간메모리
543367alextodoran분수 공원 (IOI21_parks)C++17
100 / 100
1468 ms146380 KiB
/**
 ____ ____ ____ ____ ____
||a |||t |||o |||d |||o ||
||__|||__|||__|||__|||__||
|/__\|/__\|/__\|/__\|/__\|

**/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

void build (vector <int> U, vector <int> V, vector <int> A, vector <int> B);

struct Point {
    int x, y;
    int id;
};
bool operator < (const Point &u, const Point &v) {
    return make_pair(u.x, u.y) < make_pair(v.x, v.y);
}
bool operator != (const Point &u, const Point &v) {
    return make_pair(u.x, u.y) != make_pair(v.x, v.y);
}
const int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};

int N;
set <Point> fountains;
set <pair <Point, Point>> roads;
set <Point> benches;
set <Point> squares;

map <Point, vector <Point>> adj;

set <Point> seen;
void DFS (Point s) {
    seen.insert(s);
    for (Point t : adj[s]) {
        if (seen.find(t) == seen.end()) {
            if (s.x == t.x) {
                roads.erase(make_pair(Point{s.x - 1, (s.y + t.y) / 2}, Point{s.x + 1, (s.y + t.y) / 2}));
            } else {
                roads.erase(make_pair(Point{(s.x + t.x) / 2, s.y - 1}, Point{(s.x + t.x) / 2, s.y + 1}));
            }
            DFS(t);
        }
    }
}

set <pair <Point, Point>> used;

map <Point, Point> root;
Point findRoot (Point u) {
    if (root.find(u) == root.end()) {
        return u;
    } else {
        return root[u] = findRoot(root[u]);
    }
}
bool join (Point u, Point v) {
    u = findRoot(u);
    v = findRoot(v);
    if (u != v) {
        root[u] = v;
        return true;
    } else {
        return false;
    }
}

int construct_roads (vector <int> X, vector <int> Y) {
    N = (int) X.size();
    for (int i = 0; i < N; i++) {
        fountains.insert(Point{X[i], Y[i], i});
    }
    // Find all usable benches
    for (Point f : fountains) {
        for (int d = 0; d < 2; d++) {
            Point g = Point{f.x + dx[d] * 2, f.y + dy[d] * 2};
            if (fountains.find(g) != fountains.end()) {
                roads.insert(make_pair(f, g));
                if (f.x == g.x) {
                    benches.insert(Point{f.x - 1, (f.y + g.y) / 2});
                    benches.insert(Point{f.x + 1, (f.y + g.y) / 2});
                } else {
                    benches.insert(Point{(f.x + g.x) / 2, g.y - 1});
                    benches.insert(Point{(f.x + g.x) / 2, g.y + 1});
                }
            }
        }
    }
    // Find all squares
    for (Point f : fountains) {
        bool isSquare = true;
        for (int dx : {0, +2}) {
            for (int dy : {0, +2}) {
                isSquare &= (fountains.find(Point{f.x + dx, f.y + dy}) != fountains.end());
            }
        }
        if (isSquare == true) {
            squares.insert(Point{f.x + 1, f.y + 1});
        }
    }
    // Build the dual graph
    for (Point s : squares) {
        for (int d = abs(s.x + s.y) / 2 % 2; d < 4; d += 2) {
            Point t = Point{s.x + dx[d] * 2, s.y + dy[d] * 2};
            if (squares.find(t) == squares.end()) {
                adj[Point{-7, -7}].push_back(t);
            }
            adj[t].push_back(s);
        }
    }
    // Run DFS and cut edges
    DFS(Point{-7, -7});
    for (pair <Point, Point> r : roads) {
        if (join(r.first, r.second) == true) {
            used.insert(r);
        }
    }
    if ((int) used.size() < N - 1) {
        return 0;
    }
    // Build answer
    vector <int> U, V, A, B;
    for (Point b : benches) {
        if (abs(b.x + b.y) / 2 % 2 == 1) {
            for (int dx : {-1, +1}) {
                Point f = Point{b.x + dx, b.y - 1};
                Point g = Point{b.x + dx, b.y + 1};
                if (used.find(make_pair(f, g)) != used.end()) {
                    U.push_back(fountains.find(f)->id);
                    V.push_back(fountains.find(g)->id);
                    A.push_back(b.x);
                    B.push_back(b.y);
                }
            }
        } else {
            for (int dy : {-1, +1}) {
                Point f = Point{b.x - 1, b.y + dy};
                Point g = Point{b.x + 1, b.y + dy};
                if (used.find(make_pair(f, g)) != used.end()) {
                    U.push_back(fountains.find(f)->id);
                    V.push_back(fountains.find(g)->id);
                    A.push_back(b.x);
                    B.push_back(b.y);
                }
            }
        }
    }
    build(U, V, A, B);
    return 1;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...