This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
// #include "Joi.h"
void Joi(int N, int M, int A[], int B[], long long X, int T);
void MessageBoard(int attr, int msg);
// #include "Ioi.h"
long long Ioi(int N, int M, int A[], int B[], int P, int V, int T);
int Move(int dest);
#include <vector>
#include <set>
#include <map>
#include <cstdio>
#include <cassert>
#define XMAX 60
#define NMAX 10000
#define MMAX 20000
#define MOVEMAX 20000
#define NDEBUG
using namespace std;
// ############################################################################################################
class Node {
public:
set<int> edges;
Node();
void add_edge(int neighbor);
bool is_leaf();
};
// ############################################################################################################
class Graph {
private:
typedef map<int, Node> nodes_t;
nodes_t nodes;
public:
Graph();
Graph(int N, int M, int A[], int B[]);
Graph(const Graph &T, bool allow_cycles = true, int max_size = -1);
Node & operator[] (int id);
void add_node(int id, int from = -1); // from = -1 means no from
void build_subgraph_coverage(int size);
bool has_node(int id);
void remove_node(int id);
size_t size();
int trim(int protected_id); // Trim a leaf node (but not protected_id)
};
// ############################################################################################################
class Attraction {
public:
Graph subgraph;
int index;
Attraction();
bool has_index();
};
static vector<Attraction> Park;
// ############################################################################################################
class Bits {
private:
int x[XMAX];
public:
Bits(long long X);
long long get();
int get_bit(int index);
void set_bit(int index, int bit);
};
// ############################################################################################################
// class Node
// ############################################################################################################
// ############################################################################################################
Node::Node()
: edges()
{}
// ############################################################################################################
void Node::add_edge(int neighbor)
{
edges.insert(neighbor);
}
// ############################################################################################################
bool Node::is_leaf()
{
return edges.size() <= 1;
}
// ############################################################################################################
// class Graph
// ############################################################################################################
// ############################################################################################################
Graph::Graph()
: nodes()
{}
// ############################################################################################################
Graph::Graph(int N, int M, int A[], int B[])
: nodes()
{
for ( int i = 0; i < M; ++i ) {
nodes[A[i]].add_edge(B[i]); // This will create nodes[A[i]] if necessary
nodes[B[i]].add_edge(A[i]); // ... idem for nodes[B[i]]
}
}
// ############################################################################################################
Graph::Graph(const Graph &T, bool allow_cycles, int max_size)
: nodes()
{
vector<int> pending = { T.nodes.begin()->first }; // List of nodes pending processing
set<int> done;
add_node(pending[0]); // All pending nodes are added already
while ( pending.size() > 0 ) {
int current = pending.back();
pending.pop_back();
done.insert(current);
for ( auto &&neighbor: T.nodes.at(current).edges ) {
if ( (max_size >= 0) && ((int)size() >= max_size) ) {
return;
}
if ( done.count(neighbor) ) {
continue;
}
if ( allow_cycles || !has_node(neighbor) ) {
add_node(neighbor, current);
pending.push_back(neighbor);
}
}
}
}
// ############################################################################################################
Node & Graph::operator[] (int id)
{
return nodes[id];
}
// ############################################################################################################
void Graph::add_node(int id, int from)
{
if ( !has_node(id) ) {
nodes[id] = Node();
}
if ( from >= 0 ) {
nodes[id].add_edge(from);
nodes[from].add_edge(id);
}
}
// ############################################################################################################
void Graph::build_subgraph_coverage(int size)
{
Graph S = Graph(*this, false, size);
int index = 0;
vector<int> pending; // List of nodes whose neighbors must be processed
for ( auto &&node : S.nodes ) {
int id = node.first;
Park[id].index = index;
Park[id].subgraph = S;
#if !defined(NDEBUG)
printf("Park[%d].index = %d\n",id,index);
#endif
pending.push_back(id);
index++;
}
while ( pending.size() > 0 ) {
int current = pending.back();
pending.pop_back();
for ( auto &&neighbor: nodes.at(current).edges ) {
if ( Park[neighbor].has_index() ) {
continue; // Ignore nodes that we processed already (no infinite loop)
}
Graph S = Park[current].subgraph;
int index = Park[S.trim(current)].index;
assert(index<XMAX);
S.add_node(neighbor, current);
Park[neighbor].index = index;
Park[neighbor].subgraph = S;
#if !defined(NDEBUG)
printf("Park[%d].index = %d\n",neighbor,index);
#endif
pending.push_back(neighbor);
}
}
}
// ############################################################################################################
bool Graph::has_node(int id)
{
return nodes.count(id) > 0;
}
// ############################################################################################################
void Graph::remove_node(int id)
{
for ( auto &&neighbor: nodes[id].edges ) {
nodes[neighbor].edges.erase(id);
}
nodes.erase(id);
}
// ############################################################################################################
size_t Graph::size()
{
return nodes.size();
}
// ############################################################################################################
// Trim a leaf node (but not protected_id). Return id of trimmed node.
int Graph::trim(int protected_id)
{
for ( auto &&node: nodes ) {
int id = node.first;
if ( (id != protected_id) && node.second.is_leaf() ) {
remove_node(id);
return id;
}
}
throw std::runtime_error("no unprotected leaf found.");
}
// ############################################################################################################
// class Attraction
// ############################################################################################################
// ############################################################################################################
Attraction::Attraction()
: subgraph(), index(-1)
{}
// ############################################################################################################
bool Attraction::has_index()
{
return index >= 0;
}
// ############################################################################################################
// class Bits
// ############################################################################################################
// ############################################################################################################
Bits::Bits(long long X)
{
for ( int i = 0; i < XMAX; i++ ) {
this->x[i] = X & 1;
X >>= 1;
}
}
// ############################################################################################################
long long Bits::get()
{
long long X = 0;
for ( int i = XMAX - 1; i >= 0; i-- ) {
X <<= 1;
X |= x[i];
}
return X;
}
// ############################################################################################################
int Bits::get_bit(int index)
{
return x[index];
}
// ############################################################################################################
void Bits::set_bit(int index, int bit)
{
x[index] = bit;
}
// ############################################################################################################
// Joi
// ############################################################################################################
#if defined(JOIGRADER)
// ############################################################################################################
void Joi(int N, int M, int A[], int B[], long long X, int T)
{
Bits XB(X); // Convert 60-bit X into an array of bits
Graph G(N, M, A, B);
Graph ST(G, false); // ST = graph spanning tree (no cycles)
#if !defined(NDEBUG)
printf("Joi(N=%d,M=%d)\n",N,M);
#endif
Park.resize(N);
ST.build_subgraph_coverage(XMAX); // Cover the spanning tree with subtrees of size XMAX
for ( int id = 0; id < (int)Park.size(); ++id ) {
#if !defined(NDEBUG)
printf("[id=%3d,index=%2d] = %d\n", id, Park[id].index, XB.get_bit(Park[id].index));
#endif
MessageBoard( id, XB.get_bit(Park[id].index) );
}
}
#endif
// ############################################################################################################
// Ioi
// ############################################################################################################
#if defined(IOIGRADER)
// ############################################################################################################
void IoiVisit(Graph &S, int parent, int msg, Bits &XB, set<int> &visited)
{
XB.set_bit(Park[parent].index, msg);
visited.insert(parent);
for ( auto &&child : S[parent].edges ) {
if ( visited.count(child) > 0 ) {
continue; // Ignore parent
}
int childMsg = Move(child);
IoiVisit(S, child, childMsg, XB, visited);
Move(parent);
}
}
// ############################################################################################################
// P = current node id, V = msg of current node
long long Ioi(int N, int M, int A[], int B[], int P, int V, int T)
{
Bits XB(0); // This will contain our 60-bit X (as an array of bits)
Graph G(N, M, A, B);
Graph ST(G, false); // ST = graph spanning tree (no cycles)
Park.resize(N);
ST.build_subgraph_coverage(XMAX); // Cover the spanning tree with subtrees of size XMAX
Graph S = Park[P].subgraph;
set<int> visited;
IoiVisit(S, P, V, XB, visited);
return XB.get();
}
#endif
// #include "Joi.h"
void Joi(int N, int M, int A[], int B[], long long X, int T);
void MessageBoard(int attr, int msg);
// #include "Ioi.h"
long long Ioi(int N, int M, int A[], int B[], int P, int V, int T);
int Move(int dest);
#include <vector>
#include <set>
#include <map>
#include <cstdio>
#include <cassert>
#define XMAX 60
#define NMAX 10000
#define MMAX 20000
#define MOVEMAX 20000
#define NDEBUG
using namespace std;
// ############################################################################################################
class Node {
public:
set<int> edges;
Node();
void add_edge(int neighbor);
bool is_leaf();
};
// ############################################################################################################
class Graph {
private:
typedef map<int, Node> nodes_t;
nodes_t nodes;
public:
Graph();
Graph(int N, int M, int A[], int B[]);
Graph(const Graph &T, bool allow_cycles = true, int max_size = -1);
Node & operator[] (int id);
void add_node(int id, int from = -1); // from = -1 means no from
void build_subgraph_coverage(int size);
bool has_node(int id);
void remove_node(int id);
size_t size();
int trim(int protected_id); // Trim a leaf node (but not protected_id)
};
// ############################################################################################################
class Attraction {
public:
Graph subgraph;
int index;
Attraction();
bool has_index();
};
static vector<Attraction> Park;
// ############################################################################################################
class Bits {
private:
int x[XMAX];
public:
Bits(long long X);
long long get();
int get_bit(int index);
void set_bit(int index, int bit);
};
// ############################################################################################################
// class Node
// ############################################################################################################
// ############################################################################################################
Node::Node()
: edges()
{}
// ############################################################################################################
void Node::add_edge(int neighbor)
{
edges.insert(neighbor);
}
// ############################################################################################################
bool Node::is_leaf()
{
return edges.size() <= 1;
}
// ############################################################################################################
// class Graph
// ############################################################################################################
// ############################################################################################################
Graph::Graph()
: nodes()
{}
// ############################################################################################################
Graph::Graph(int N, int M, int A[], int B[])
: nodes()
{
for ( int i = 0; i < M; ++i ) {
nodes[A[i]].add_edge(B[i]); // This will create nodes[A[i]] if necessary
nodes[B[i]].add_edge(A[i]); // ... idem for nodes[B[i]]
}
}
// ############################################################################################################
Graph::Graph(const Graph &T, bool allow_cycles, int max_size)
: nodes()
{
vector<int> pending = { T.nodes.begin()->first }; // List of nodes pending processing
set<int> done;
add_node(pending[0]); // All pending nodes are added already
while ( pending.size() > 0 ) {
int current = pending.back();
pending.pop_back();
done.insert(current);
for ( auto &&neighbor: T.nodes.at(current).edges ) {
if ( (max_size >= 0) && ((int)size() >= max_size) ) {
return;
}
if ( done.count(neighbor) ) {
continue;
}
if ( allow_cycles || !has_node(neighbor) ) {
add_node(neighbor, current);
pending.push_back(neighbor);
}
}
}
}
// ############################################################################################################
Node & Graph::operator[] (int id)
{
return nodes[id];
}
// ############################################################################################################
void Graph::add_node(int id, int from)
{
if ( !has_node(id) ) {
nodes[id] = Node();
}
if ( from >= 0 ) {
nodes[id].add_edge(from);
nodes[from].add_edge(id);
}
}
// ############################################################################################################
void Graph::build_subgraph_coverage(int size)
{
Graph S = Graph(*this, false, size);
int index = 0;
vector<int> pending; // List of nodes whose neighbors must be processed
for ( auto &&node : S.nodes ) {
int id = node.first;
Park[id].index = index;
Park[id].subgraph = S;
#if !defined(NDEBUG)
printf("Park[%d].index = %d\n",id,index);
#endif
pending.push_back(id);
index++;
}
while ( pending.size() > 0 ) {
int current = pending.back();
pending.pop_back();
for ( auto &&neighbor: nodes.at(current).edges ) {
if ( Park[neighbor].has_index() ) {
continue; // Ignore nodes that we processed already (no infinite loop)
}
Graph S = Park[current].subgraph;
int index = Park[S.trim(current)].index;
assert(index<XMAX);
S.add_node(neighbor, current);
Park[neighbor].index = index;
Park[neighbor].subgraph = S;
#if !defined(NDEBUG)
printf("Park[%d].index = %d\n",neighbor,index);
#endif
pending.push_back(neighbor);
}
}
}
// ############################################################################################################
bool Graph::has_node(int id)
{
return nodes.count(id) > 0;
}
// ############################################################################################################
void Graph::remove_node(int id)
{
for ( auto &&neighbor: nodes[id].edges ) {
nodes[neighbor].edges.erase(id);
}
nodes.erase(id);
}
// ############################################################################################################
size_t Graph::size()
{
return nodes.size();
}
// ############################################################################################################
// Trim a leaf node (but not protected_id). Return id of trimmed node.
int Graph::trim(int protected_id)
{
for ( auto &&node: nodes ) {
int id = node.first;
if ( (id != protected_id) && node.second.is_leaf() ) {
remove_node(id);
return id;
}
}
throw std::runtime_error("no unprotected leaf found.");
}
// ############################################################################################################
// class Attraction
// ############################################################################################################
// ############################################################################################################
Attraction::Attraction()
: subgraph(), index(-1)
{}
// ############################################################################################################
bool Attraction::has_index()
{
return index >= 0;
}
// ############################################################################################################
// class Bits
// ############################################################################################################
// ############################################################################################################
Bits::Bits(long long X)
{
for ( int i = 0; i < XMAX; i++ ) {
this->x[i] = X & 1;
X >>= 1;
}
}
// ############################################################################################################
long long Bits::get()
{
long long X = 0;
for ( int i = XMAX - 1; i >= 0; i-- ) {
X <<= 1;
X |= x[i];
}
return X;
}
// ############################################################################################################
int Bits::get_bit(int index)
{
return x[index];
}
// ############################################################################################################
void Bits::set_bit(int index, int bit)
{
x[index] = bit;
}
// ############################################################################################################
// Joi
// ############################################################################################################
#if defined(JOIGRADER)
// ############################################################################################################
void Joi(int N, int M, int A[], int B[], long long X, int T)
{
Bits XB(X); // Convert 60-bit X into an array of bits
Graph G(N, M, A, B);
Graph ST(G, false); // ST = graph spanning tree (no cycles)
#if !defined(NDEBUG)
printf("Joi(N=%d,M=%d)\n",N,M);
#endif
Park.resize(N);
ST.build_subgraph_coverage(XMAX); // Cover the spanning tree with subtrees of size XMAX
for ( int id = 0; id < (int)Park.size(); ++id ) {
#if !defined(NDEBUG)
printf("[id=%3d,index=%2d] = %d\n", id, Park[id].index, XB.get_bit(Park[id].index));
#endif
MessageBoard( id, XB.get_bit(Park[id].index) );
}
}
#endif
// ############################################################################################################
// Ioi
// ############################################################################################################
#if defined(IOIGRADER)
// ############################################################################################################
void IoiVisit(Graph &S, int parent, int msg, Bits &XB, set<int> &visited)
{
XB.set_bit(Park[parent].index, msg);
visited.insert(parent);
for ( auto &&child : S[parent].edges ) {
if ( visited.count(child) > 0 ) {
continue; // Ignore parent
}
int childMsg = Move(child);
IoiVisit(S, child, childMsg, XB, visited);
Move(parent);
}
}
// ############################################################################################################
// P = current node id, V = msg of current node
long long Ioi(int N, int M, int A[], int B[], int P, int V, int T)
{
Bits XB(0); // This will contain our 60-bit X (as an array of bits)
Graph G(N, M, A, B);
Graph ST(G, false); // ST = graph spanning tree (no cycles)
Park.resize(N);
ST.build_subgraph_coverage(XMAX); // Cover the spanning tree with subtrees of size XMAX
Graph S = Park[P].subgraph;
set<int> visited;
IoiVisit(S, P, V, XB, visited);
return XB.get();
}
#endif
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |