Skip to content

Commit

Permalink
Merge pull request #1207 from NachiaVivias/euclid_mst
Browse files Browse the repository at this point in the history
問題追加 Euclidean MST
  • Loading branch information
maspypy authored Jul 13, 2024
2 parents b4f8e98 + c63cb9e commit f59a877
Show file tree
Hide file tree
Showing 19 changed files with 1,131 additions and 0 deletions.
91 changes: 91 additions & 0 deletions geo/euclidean_mst/checker.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include <algorithm>
#include <vector>
#include <utility>
#include "testlib.h"

using namespace std;
using ll = long long;


struct DsuFast{
private:
std::vector<int> w;
public:
DsuFast(int n = 0) : w(n, -1) {}
int leader(int u){
if(w[u] < 0) return u;
return w[u] = leader(w[u]);
}
int operator[](int u){ return leader(u); }
int merge(int u, int v){
u = leader(u);
v = leader(v);
if(u == v) return u;
if(-w[u] < -w[v]) std::swap(u, v);
w[u] += w[v];
w[v] = u;
return u;
}
int size(int u){ return -w[leader(u)]; }
bool same(int u, int v){ return leader(u) == leader(v); }
};

int main(int argc, char* argv[]) {
registerTestlibCmd(argc, argv);


int N = inf.readInt();

vector<ll> X(N), Y(N);
for(int i=0; i<N; i++){
X[i] = inf.readInt();
Y[i] = inf.readInt();
}

auto weight = [&](int a, int b){
ll dx = X[a] - X[b];
ll dy = Y[a] - Y[b];
return dx * dx + dy * dy;
};

DsuFast dsu_ans(N);
vector<ll> weights_ans;
for(int i=0; i<N-1; i++){
int a = ans.readInt(0, N - 1);
int b = ans.readInt(0, N - 1);
dsu_ans.merge(a, b);
weights_ans.push_back(weight(a, b));
}

if(dsu_ans.size(0) != N){
quit(_fail, "the output of writer\'s solution is not connected");
}

sort(weights_ans.begin(), weights_ans.end());

DsuFast dsu_out(N);
vector<ll> weights_out;
for(int i=0; i<N-1; i++){
int a = ouf.readInt(0, N - 1);
int b = ouf.readInt(0, N - 1);
dsu_out.merge(a, b);
weights_out.push_back(weight(a, b));
}

if(dsu_out.size(0) != N){
quit(_wa, "not connected");
}

sort(weights_out.begin(), weights_out.end());

for(int i=0; i<N-1; i++){
if(weights_ans[i] > weights_out[i]){
quit(_fail, "your output showed the writer solution doesn\'t output the minumum spanning tree");
}
if(weights_ans[i] < weights_out[i]){
quit(_wa, "not the minumum cost");
}
}

quitf(_ok, "OK");
}
33 changes: 33 additions & 0 deletions geo/euclidean_mst/gen/all_same.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <cstdio>
#include <cstdlib>
#include <utility>
#include "random.h"
#include "../params.h"

using namespace std;

using P = pair<int, int>;

P random_point(Random& gen, int LIM) {
int x = gen.uniform(-LIM, LIM);
int y = gen.uniform(-LIM, LIM);
return {x, y};
}

void out(vector<P> S) {
int n = S.size();
printf("%d\n", n);
for (auto& [x, y]: S) { printf("%d %d\n", x, y); }
}

int main(int, char* argv[]) {
long long seed = atoll(argv[1]);
auto gen = Random(seed);

int n = N_MAX;
auto [x, y] = random_point(gen, X_AND_Y_ABS_MAX);
vector<P> S(n, { x,y });

out(S);
return 0;
}
6 changes: 6 additions & 0 deletions geo/euclidean_mst/gen/example_00.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
5
-1 -1
-6 4
-9 -7
2 5
-7 6
35 changes: 35 additions & 0 deletions geo/euclidean_mst/gen/max_colinear.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <cstdio>
#include <cstdlib>
#include <utility>
#include "random.h"
#include "../params.h"

using namespace std;

using P = pair<int, int>;

void out(vector<P> S) {
int n = S.size();
printf("%d\n", n);
for (auto& [x, y]: S) { printf("%d %d\n", x, y); }
}

int main(int, char* argv[]) {
long long seed = atoll(argv[1]);
auto gen = Random(seed);

int x0 = gen.uniform<int>(1, 10);
int y0 = gen.uniform<int>(1, 10);
int lim = X_AND_Y_ABS_MAX / max(x0, y0);

int n = N_MAX;
vector<P> S;
for (int i = 0; i < n; ++i) {
int t = gen.uniform<int>(-lim, lim);
int x = x0 * t, y = y0 * t;
S.emplace_back(x, y);
}

out(S);
return 0;
}
37 changes: 37 additions & 0 deletions geo/euclidean_mst/gen/max_random.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <cstdio>
#include <cstdlib>
#include <utility>
#include "random.h"
#include "../params.h"

using namespace std;

using P = pair<int, int>;

P random_point(Random& gen, int LIM) {
int x = gen.uniform(-LIM, LIM);
int y = gen.uniform(-LIM, LIM);
return {x, y};
}

void out(vector<P> S) {
int n = S.size();
printf("%d\n", n);
for (auto& [x, y]: S) { printf("%d %d\n", x, y); }
}

int main(int, char* argv[]) {
long long seed = atoll(argv[1]);
auto gen = Random(seed);

int lims[] = { 10, 1000, X_AND_Y_ABS_MAX, X_AND_Y_ABS_MAX };

int LIM = lims[seed % 4];

int n = N_MAX;
vector<P> S;
for (int i = 0; i < n; ++i) S.emplace_back(random_point(gen, LIM));

out(S);
return 0;
}
52 changes: 52 additions & 0 deletions geo/euclidean_mst/gen/max_slender.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <cstdio>
#include <cstdlib>
#include <utility>
#include <algorithm>
#include "random.h"
#include "../params.h"

using namespace std;

using P = pair<int, int>;

void out(vector<P> S) {
int n = S.size();
printf("%d\n", n);
for (auto& [x, y]: S) { printf("%d %d\n", x, y); }
}

int main(int, char* argv[]) {
long long seed = atoll(argv[1]);
auto gen = Random(seed);

int n = N_MAX;
int h = 100;
int w = X_AND_Y_ABS_MAX - h;

vector<P> S;
for(int i=0; i<n; i++){
int x = gen.uniform<int>(-w, w);
int y = gen.uniform<int>(-h, h);
S.push_back(make_pair(x, y));
}

if(seed == 1){
for(auto& a : S){
swap(a.first, a.second);
}
}
else if(seed == 2){
for(auto& a : S){
a.second += a.first;
}
}
else if(seed == 3){
for(auto& a : S){
a.second -= a.first;
}
}


out(S);
return 0;
}
37 changes: 37 additions & 0 deletions geo/euclidean_mst/gen/mid_random.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <cstdio>
#include <cstdlib>
#include <utility>
#include "random.h"
#include "../params.h"

using namespace std;

using P = pair<int, int>;

P random_point(Random& gen, int LIM) {
int x = gen.uniform(-LIM, LIM);
int y = gen.uniform(-LIM, LIM);
return {x, y};
}

void out(vector<P> S) {
int n = S.size();
printf("%d\n", n);
for (auto& [x, y]: S) { printf("%d %d\n", x, y); }
}

int main(int, char* argv[]) {
long long seed = atoll(argv[1]);
auto gen = Random(seed);

int lims[] = { 10, 1000, X_AND_Y_ABS_MAX, X_AND_Y_ABS_MAX };

int LIM = lims[seed % 4];

int n = gen.uniform<int>(100, 1000);
vector<P> S;
for (int i = 0; i < n; ++i) S.emplace_back(random_point(gen, LIM));

out(S);
return 0;
}
2 changes: 2 additions & 0 deletions geo/euclidean_mst/gen/min_00.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1
0 0
3 changes: 3 additions & 0 deletions geo/euclidean_mst/gen/min_01.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
2
0 0
0 1
3 changes: 3 additions & 0 deletions geo/euclidean_mst/gen/min_02.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
2
0 0
0 0
41 changes: 41 additions & 0 deletions geo/euclidean_mst/gen/near_circle.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <cstdio>
#include <cstdlib>
#include <utility>
#include "random.h"
#include "../params.h"

using namespace std;

using P = pair<int, int>;

P random_point(Random& gen) {
long long R = X_AND_Y_ABS_MAX;
long long x = gen.uniform(-R, R);
long long ok = 0, ng = R + 1;
while (ok + 1 < ng) {
long long mi = (ok + ng) / 2;
(x * x + mi * mi <= R * R ? ok : ng) = mi;
}
long long y = ok;
if (gen.uniform<int>(0, 1)) y = -y;
if (gen.uniform<int>(0, 1)) swap(x, y);
return {x, y};
}

void out(vector<P> S) {
int n = S.size();
printf("%d\n", n);
for (auto& [x, y]: S) { printf("%d %d\n", x, y); }
}

int main(int, char* argv[]) {
long long seed = atoll(argv[1]);
auto gen = Random(seed);

int n = N_MAX;
vector<P> S;
for (int i = 0; i < n; ++i) S.emplace_back(random_point(gen));

out(S);
return 0;
}
Loading

0 comments on commit f59a877

Please sign in to comment.