This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
#include <algorithm>
#include <iostream>
#include "../../graph/read_graph.hpp"
#include "../../graph/topological_sort.hpp"
#include "../../random/base.hpp"
void test1_lexicographical_order() {
// 旧: https://atcoder.jp/contests/abc223/tasks/abc223_d
const int n = 200;
// 0 -> 1 -> n - 1
// 0 -> 2 -> n - 1
// をランダムな順序で張っていき, トポソする
std::vector<std::pair<int, int>> p;
for (int i = 1; i < n - 1; i++) {
p.push_back({rng_auto.rand_int(), i});
}
std::sort(p.begin(), p.end());
Graph<int> g(n, true);
for (int i = 0; i < n - 2; i++) {
g.add_edge(0, p[i].second);
g.add_edge(p[i].second, n - 1);
}
auto vec = topological_sort(g);
for (int i = 0; i < n; i++) {
assert(vec[i] == i);
}
}
int main() {
test1_lexicographical_order();
int a, b;
std::cin >> a >> b;
std::cout << a + b << '\n';
return 0;
}#line 1 "verify/graph/topological_sort_lexicographical_order.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/aplusb"
#include <algorithm>
#include <iostream>
#line 2 "graph/read_graph.hpp"
#line 2 "graph/graph_template.hpp"
#include <cassert>
#include <vector>
template <class T> struct Edge {
int from, to;
T cost;
int id;
Edge() = default;
Edge(const int from, const int to, const T cost = T(1), const int id = -1)
: from(from), to(to), cost(cost), id(id) {}
friend bool operator<(const Edge<T>& a, const Edge<T>& b) {
return a.cost < b.cost;
}
friend std::ostream& operator<<(std::ostream& os, const Edge<T>& e) {
// output format: {id: cost(from, to) = cost}
return os << "{" << e.id << ": cost(" << e.from << ", " << e.to
<< ") = " << e.cost << "}";
}
};
template <class T> using Edges = std::vector<Edge<T>>;
template <class T> struct Graph {
struct EdgeIterators {
public:
using Iterator = typename std::vector<Edge<T>>::iterator;
EdgeIterators() = default;
EdgeIterators(const Iterator& begit, const Iterator& endit)
: begit(begit), endit(endit) {}
Iterator begin() const { return begit; }
Iterator end() const { return endit; }
size_t size() const { return std::distance(begit, endit); }
Edge<T>& operator[](int i) const { return begit[i]; }
private:
Iterator begit, endit;
};
int n, m;
bool is_build, is_directed;
std::vector<Edge<T>> edges;
// CSR (Compressed Row Storage) 形式用
std::vector<int> start;
std::vector<Edge<T>> csr_edges;
Graph() = default;
Graph(const int n, const bool directed = false)
: n(n), m(0), is_build(false), is_directed(directed), start(n + 1, 0) {}
// 辺を追加し, その辺が何番目に追加されたかを返す
int add_edge(const int from,
const int to,
const T cost = T(1),
int id = -1) {
assert(!is_build);
assert(0 <= from and from < n);
assert(0 <= to and to < n);
if (id == -1) id = m;
edges.emplace_back(from, to, cost, id);
return m++;
}
// CSR 形式でグラフを構築
void build() {
assert(!is_build);
for (auto&& e : edges) {
start[e.from + 1]++;
if (!is_directed) start[e.to + 1]++;
}
for (int v = 0; v < n; v++) start[v + 1] += start[v];
auto counter = start;
csr_edges.resize(start.back() + 1);
for (auto&& e : edges) {
csr_edges[counter[e.from]++] = e;
if (!is_directed)
csr_edges[counter[e.to]++] = Edge(e.to, e.from, e.cost, e.id);
}
is_build = true;
}
EdgeIterators operator[](int i) {
if (!is_build) build();
return EdgeIterators(csr_edges.begin() + start[i],
csr_edges.begin() + start[i + 1]);
}
size_t size() const { return (size_t)(n); }
friend std::ostream& operator<<(std::ostream& os, Graph<T>& g) {
os << "[";
for (int i = 0; i < (int)(g.size()); i++) {
os << "[";
for (int j = 0; j < (int)(g[i].size()); j++) {
os << g[i][j];
if (j + 1 != (int)(g[i].size())) os << ", ";
}
os << "]";
if (i + 1 != (int)(g.size())) os << ", ";
}
return os << "]";
}
};
#line 4 "graph/read_graph.hpp"
template <class T>
Graph<T> read_graph(const int n,
const int m,
const bool weight = false,
const bool directed = false,
const int offset = 1) {
Graph<T> g(n, directed);
for (int i = 0; i < m; i++) {
int a, b;
std::cin >> a >> b;
a -= offset, b -= offset;
T c = 1;
if (weight) std::cin >> c;
g.add_edge(a, b, c);
}
g.build();
return g;
}
template <class T>
Graph<T> read_parent(const int n,
const bool weight = false,
const bool directed = false,
const int offset = 1) {
Graph<T> g(n, directed);
for (int i = 1; i < n; i++) {
int p;
std::cin >> p;
p -= offset;
T c = 1;
if (weight) std::cin >> c;
g.add_edge(p, i, c);
}
g.build();
return g;
}
#line 2 "graph/topological_sort.hpp"
#line 4 "graph/topological_sort.hpp"
#line 6 "graph/topological_sort.hpp"
#include <queue>
// topological sort が存在するなら, 辞書順最小のものを返す
// O((n + m) log n)
// topological sort が一意に定まる <=> 最長パスの長さが n - 1
template <class T> std::vector<int> topological_sort(Graph<T>& g) {
const int n = (int)(g.size());
assert(n > 0);
std::vector<int> indeg(n, 0);
for (int i = 0; i < n; i++) {
for (auto&& e : g[i]) indeg[e.to]++;
}
// O(n + m) にしたい場合は std::queue にする
std::priority_queue<int, std::vector<int>, std::greater<>> que;
for (int i = 0; i < n; i++) {
if (indeg[i] == 0) {
que.push(i);
}
}
std::vector<int> res;
while (!que.empty()) {
auto v = que.top();
que.pop();
res.push_back(v);
for (auto&& e : g[v]) {
indeg[e.to]--;
if (indeg[e.to] == 0) que.push(e.to);
}
}
// topological sort できない
if ((int)(res.size()) != n) {
return std::vector<int>();
}
return res;
}
#line 2 "random/base.hpp"
#line 4 "random/base.hpp"
#include <chrono>
#include <cstdint>
#line 2 "misc/topbit.hpp"
#line 2 "misc/countl_zero.hpp"
#if __cplusplus >= 202002L
#include <bit>
#endif
// countl_zero
// (000, 001, 010, 011, 100) -> (32, 31, 30, 30, 29)
#if __cplusplus >= 202002L
using std::countl_zero;
#else
int countl_zero(unsigned int x) {
return x == 0 ? 32 : __builtin_clz(x);
}
int countl_zero(unsigned long long int x) {
return x == 0 ? 64 : __builtin_clzll(x);
}
#endif
int countl_zero(int x) { return countl_zero((unsigned int)(x)); }
int countl_zero(long long int x) {
return countl_zero((unsigned long long int)(x));
}
#line 4 "misc/topbit.hpp"
// topbit
// (000, 001, 010, 011, 100) -> (-1, 0, 1, 1, 2)
int topbit(int x) { return 31 - countl_zero(x); }
int topbit(unsigned int x) { return 31 - countl_zero(x); }
int topbit(long long int x) { return 63 - countl_zero(x); }
int topbit(unsigned long long int x) { return 63 - countl_zero(x); }
#line 8 "random/base.hpp"
template <bool auto_seed> struct Random {
uint64_t x_seed;
Random(uint64_t seed = 0) {
if (auto_seed) {
// set random seed
assert(seed == 0);
x_seed =
std::chrono::steady_clock::now().time_since_epoch().count();
} else {
// set seed
x_seed = seed;
}
}
// http://xorshift.di.unimi.it/splitmix64.c
// [0, 2^64 - 1]
uint64_t rand_int() {
uint64_t z = (x_seed += 0x9e3779b97f4a7c15);
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
return z ^ (z >> 31);
}
// [0, mod - 1]
// rand_int() % mod だと mod が 2 べきでないときに偏る
uint64_t rand_int(uint64_t mod) {
assert(mod > 0);
if ((mod & (mod - 1)) == 0) {
// mod = 2^p
// (mod - 1) = 0...01...1
return rand_int() & (mod - 1);
}
// mod >= 3 (1 = 2^0, 2 = 2^1)
int lg = topbit((unsigned long long)mod);
uint64_t mask = (lg == 63) ? ~0ULL : (1ULL << (lg + 1)) - 1;
while (true) {
uint64_t r = rand_int() & mask;
if (r < mod) return r;
}
}
// [l, r]
template <class T> T rand_int(T l, T r) {
assert(l <= r);
return T(l + rand_int(uint64_t(r - l + 1)));
}
// [0.0, 1.0]
double rand_double() {
uint64_t v = rand_int(1ULL << 63);
return double(v) / ((1ULL << 63) - 1);
}
// [l, r]
double rand_double(double l, double r) {
assert(l <= r);
return l + rand_double() * (r - l);
}
};
using RandomFixed = Random<false>;
using RandomAuto = Random<true>;
RandomAuto rng_auto;
#line 9 "verify/graph/topological_sort_lexicographical_order.test.cpp"
void test1_lexicographical_order() {
// 旧: https://atcoder.jp/contests/abc223/tasks/abc223_d
const int n = 200;
// 0 -> 1 -> n - 1
// 0 -> 2 -> n - 1
// をランダムな順序で張っていき, トポソする
std::vector<std::pair<int, int>> p;
for (int i = 1; i < n - 1; i++) {
p.push_back({rng_auto.rand_int(), i});
}
std::sort(p.begin(), p.end());
Graph<int> g(n, true);
for (int i = 0; i < n - 2; i++) {
g.add_edge(0, p[i].second);
g.add_edge(p[i].second, n - 1);
}
auto vec = topological_sort(g);
for (int i = 0; i < n; i++) {
assert(vec[i] == i);
}
}
int main() {
test1_lexicographical_order();
int a, b;
std::cin >> a >> b;
std::cout << a + b << '\n';
return 0;
}