#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <queue>
#include <set>
#include <map>
#include <numeric>
#include <utility>
#include <string>
#include <sstream>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>
#include "kollib.h"
#include "message.h"
using namespace std;
unordered_set<int> points;
vector<int> points2;
unordered_map<int, pair< pair<int,int>, pair<int,int> > > dist;
vector<pair<int,int> > queries;
int n, m;
int nn, id;
pair<int,int> go(int a, int b) {
int r = 0;
while (!points.count(a)) {
++r;
int t = FirstNeighbor(a);
if (t == b) t = SecondNeighbor(a);
b = a;
a = t;
}
return make_pair(a, r);
}
pair<pair<int,int>, pair<int, int> > go(int i) {
auto a = go(FirstNeighbor(i), i);
auto b = go(SecondNeighbor(i), i);
++a.second;
++b.second;
return make_pair(a, b);
}
int go2(int a, int b, int c) {
int r = 0;
while (a != c) {
auto x = dist[a].first;
if (x.first == b) {
x = dist[a].second;
}
r += x.second;
b = a;
a = x.first;
}
return r;
}
int go2(int a, int b) {
if (a == b) return 0;
int r = min(dist[a].first.second + go2(dist[a].first.first, a, b),
dist[a].second.second + go2(dist[a].second.first, a, b));
return r;
}
int main() {
n = NumberOfStudents();
m = NumberOfQueries();
if (!m) return 0;
nn = NumberOfNodes();
id = MyNodeId();
queries.clear();
queries.resize(m);
points.clear();
points2.clear();
dist.clear();
for (int i = 0; i < m; ++i) {
queries[i].first = QueryFrom(i + 1);
queries[i].second = QueryTo(i + 1);
if (points.insert(queries[i].first).second)
points2.push_back(queries[i].first);
if (points.insert(queries[i].second).second)
points2.push_back(queries[i].second);
}
srand(1212121);
int pn = min(800, m / 100);
while (points.size() < pn) {
int rnd = rand() % n + 1;
if (points.insert(rnd).second)
points2.push_back(rnd);
}
for (size_t i = id; i < points2.size(); i += nn) {
if (id == nn - 1) {
dist[points2[i]] = go(points2[i]);
} else {
auto r = go(points2[i]);
PutInt(nn - 1, points2[i]);
PutInt(nn - 1, r.first.first);
PutInt(nn - 1, r.first.second);
PutInt(nn - 1, r.second.first);
PutInt(nn - 1, r.second.second);
Send(nn - 1);
}
}
if (id == nn - 1) {
for (size_t i = 0; i < points2.size(); ++i) {
if (i % nn == id)
continue;
int src = Receive(-1);
int pi = GetInt(src);
pair<pair<int, int>, pair<int, int> > p;
p.first.first = GetInt(src);
p.first.second = GetInt(src);
p.second.first = GetInt(src);
p.second.second = GetInt(src);
dist[pi] = p;
}
for (int i = 0; i < m; ++i) {
printf("%d\n", go2(queries[i].first, queries[i].second));
}
}
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <list> #include <queue> #include <set> #include <map> #include <numeric> #include <utility> #include <string> #include <sstream> #include <algorithm> #include <unordered_set> #include <unordered_map> #include "kollib.h" #include "message.h" using namespace std; unordered_set<int> points; vector<int> points2; unordered_map<int, pair< pair<int,int>, pair<int,int> > > dist; vector<pair<int,int> > queries; int n, m; int nn, id; pair<int,int> go(int a, int b) { int r = 0; while (!points.count(a)) { ++r; int t = FirstNeighbor(a); if (t == b) t = SecondNeighbor(a); b = a; a = t; } return make_pair(a, r); } pair<pair<int,int>, pair<int, int> > go(int i) { auto a = go(FirstNeighbor(i), i); auto b = go(SecondNeighbor(i), i); ++a.second; ++b.second; return make_pair(a, b); } int go2(int a, int b, int c) { int r = 0; while (a != c) { auto x = dist[a].first; if (x.first == b) { x = dist[a].second; } r += x.second; b = a; a = x.first; } return r; } int go2(int a, int b) { if (a == b) return 0; int r = min(dist[a].first.second + go2(dist[a].first.first, a, b), dist[a].second.second + go2(dist[a].second.first, a, b)); return r; } int main() { n = NumberOfStudents(); m = NumberOfQueries(); if (!m) return 0; nn = NumberOfNodes(); id = MyNodeId(); queries.clear(); queries.resize(m); points.clear(); points2.clear(); dist.clear(); for (int i = 0; i < m; ++i) { queries[i].first = QueryFrom(i + 1); queries[i].second = QueryTo(i + 1); if (points.insert(queries[i].first).second) points2.push_back(queries[i].first); if (points.insert(queries[i].second).second) points2.push_back(queries[i].second); } srand(1212121); int pn = min(800, m / 100); while (points.size() < pn) { int rnd = rand() % n + 1; if (points.insert(rnd).second) points2.push_back(rnd); } for (size_t i = id; i < points2.size(); i += nn) { if (id == nn - 1) { dist[points2[i]] = go(points2[i]); } else { auto r = go(points2[i]); PutInt(nn - 1, points2[i]); PutInt(nn - 1, r.first.first); PutInt(nn - 1, r.first.second); PutInt(nn - 1, r.second.first); PutInt(nn - 1, r.second.second); Send(nn - 1); } } if (id == nn - 1) { for (size_t i = 0; i < points2.size(); ++i) { if (i % nn == id) continue; int src = Receive(-1); int pi = GetInt(src); pair<pair<int, int>, pair<int, int> > p; p.first.first = GetInt(src); p.first.second = GetInt(src); p.second.first = GetInt(src); p.second.second = GetInt(src); dist[pi] = p; } for (int i = 0; i < m; ++i) { printf("%d\n", go2(queries[i].first, queries[i].second)); } } return 0; } |
English