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 <iostream>
#include <vector>
#include <queue>
#include <map>
#include <climits>
//divide and conquer for a tree
#define MAXN 100000
using namespace std;
vector<int> adj[MAXN + 5];
int N;
long long mag[MAXN + 5];
bool deleted[MAXN + 5]; // deleted after centroid marked
int sz[MAXN + 5]; // size of subtree
int head[MAXN + 5]; // head of subtree to find centroid for
queue<int> Q;
long long p = LLONG_MAX; // answer fraction
long long q = 1;
int gcd(int a, int b) {
if (b == 0)
return a;
return gcd(b, a % b);
}
void comp(long long num, long long den) { // find min fraction
long long factor = gcd(num, den);
num /= factor;
den /= factor;
if (num * q < den * p) {
p = num;
q = den;
}
}
void dfs(int x, int p, int h) { // find size for subtree
sz[x] = 1; // reset size
head[x] = h;
for (int e : adj[x]) {
if (deleted[e]) continue;
if (e == p) continue;
dfs(e, x, h);
sz[x] += sz[e];
}
}
map<int, long long> mn; // max possible product for each path length
map<int, long long> temp; // current childs subtree, compare with max for all the other children
void dfs_path(int x, int p, int len, long long prod) { // length and product of current path
if (temp[len] == 0)temp[len] = LLONG_MAX;
temp[len] = min(temp[len], prod);
for (int e : adj[x]) {
if (deleted[e]) continue;
if (e == p) continue;
dfs_path(e, x, len + 1, prod * mag[e]);
}
}
void dfs_comp(int x, int p, int len, long long prod) { // compare with other paths
for (auto path : mn) {
comp(prod * path.second, len + path.first);
}
for (int e : adj[x]) {
if (deleted[e]) continue;
if (e == p) continue;
dfs_comp(e, x, len + 1, prod * mag[e]);
}
}
int find(int x, int p, int h) { // return centroid for suntree starting at x, h head of tree
bool cent = true;
int centroid = -1;
if ((sz[h] - sz[x]) > sz[h] / 2) {
cent = false;
}
for (int e : adj[x]) {
if (deleted[e]) continue;
if (e == p) continue;
if (sz[e] > sz[h] / 2) cent = false;
}
if (cent) {
return x;
}
else {
for (int e : adj[x]) {
if (deleted[e]) continue;
if (e == p) continue;
centroid = max(centroid, find(e, x, h));
}
return centroid;
}
}
int main() {
cin >> N;
for (int i = 1; i < N; i++) {
int a, b;
cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
for (int i = 1; i <= N; i++) {
cin >> mag[i];
}
Q.push(1);
while (!Q.empty()) {
int curr = Q.front(); Q.pop();
dfs(curr, -1, curr);
int centroid = find(curr, -1, curr);
for (int c : adj[centroid]) {
if (deleted[c]) continue;
dfs_path(c, centroid, 1, mag[c]);
mn[0] = 1; // for only using the path and centroid
dfs_comp(c, centroid, 2, mag[c]*mag[centroid]);
for (auto path : temp) {
if (mn[path.first] == 0) mn[path.first] = LLONG_MAX;
mn[path.first] = min(mn[path.first], temp[path.first]);
}
temp.clear();
Q.push(c);
}
mn.clear();
deleted[centroid] = true;
}
cout << p << "/" << q;
}
# | 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... |
# | 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... |