/* 2015 * Maciej Szeptuch * II UWr */ #include <cstdio> #include <vector> #include <unordered_map> typedef long long int lld; typedef std::unordered_map<int, lld> Prices; lld bestPrice(const int _center); Prices findPrices(int v); const int MAX_STATIONS = 524288; bool processed[MAX_STATIONS]; int center; int end; int foreign; int width[MAX_STATIONS]; int start; int stations; std::vector<int> tree[MAX_STATIONS]; int main(void) { scanf("%d %d", &stations, &foreign); for(int s = 1; s < stations; ++ s) { scanf("%d %d", &start, &end); -- start; -- end; tree[start].push_back(end); tree[end].push_back(start); } for(int f = 0; f < foreign; ++ f) scanf("%d", &width[f]); // TODO: find tree center center = foreign + (stations - foreign) / 2; printf("%lld\n", bestPrice(center)); return 0; } lld bestPrice(const int _center) { lld bestPrice = -1; for(const auto &price: findPrices(_center)) if(bestPrice == -1 || price.second < bestPrice) bestPrice = price.second; return bestPrice; } Prices findPrices(int v) { Prices result; std::vector<Prices> children; processed[v] = true; for(const int &child: tree[v]) { if(processed[child]) continue; children.push_back(findPrices(child)); } if(children.size() == 0) result[width[v]] = 0; if(children.size() == 1) result = children[0]; for(const Prices &prices: children) for(const auto &price: prices) result[price.first] = -1; for(const Prices &prices: children) for(const auto &price: prices) { lld actualPrice = 0; for(const Prices &mergePrices: children) if(&mergePrices != &prices) { lld bestPrice = -1; for(const auto &mergePrice: mergePrices) if(bestPrice == -1 || bestPrice > std::abs(price.first - mergePrice.first) + price.second + mergePrice.second) bestPrice = std::abs(price.first - mergePrice.first) + price.second + mergePrice.second; actualPrice += bestPrice; if(result[price.first] != -1 && actualPrice > result[price.first]) break; } if(result[price.first] == -1 || actualPrice < result[price.first]) result[price.first] = actualPrice; } return result; }
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 | /* 2015 * Maciej Szeptuch * II UWr */ #include <cstdio> #include <vector> #include <unordered_map> typedef long long int lld; typedef std::unordered_map<int, lld> Prices; lld bestPrice(const int _center); Prices findPrices(int v); const int MAX_STATIONS = 524288; bool processed[MAX_STATIONS]; int center; int end; int foreign; int width[MAX_STATIONS]; int start; int stations; std::vector<int> tree[MAX_STATIONS]; int main(void) { scanf("%d %d", &stations, &foreign); for(int s = 1; s < stations; ++ s) { scanf("%d %d", &start, &end); -- start; -- end; tree[start].push_back(end); tree[end].push_back(start); } for(int f = 0; f < foreign; ++ f) scanf("%d", &width[f]); // TODO: find tree center center = foreign + (stations - foreign) / 2; printf("%lld\n", bestPrice(center)); return 0; } lld bestPrice(const int _center) { lld bestPrice = -1; for(const auto &price: findPrices(_center)) if(bestPrice == -1 || price.second < bestPrice) bestPrice = price.second; return bestPrice; } Prices findPrices(int v) { Prices result; std::vector<Prices> children; processed[v] = true; for(const int &child: tree[v]) { if(processed[child]) continue; children.push_back(findPrices(child)); } if(children.size() == 0) result[width[v]] = 0; if(children.size() == 1) result = children[0]; for(const Prices &prices: children) for(const auto &price: prices) result[price.first] = -1; for(const Prices &prices: children) for(const auto &price: prices) { lld actualPrice = 0; for(const Prices &mergePrices: children) if(&mergePrices != &prices) { lld bestPrice = -1; for(const auto &mergePrice: mergePrices) if(bestPrice == -1 || bestPrice > std::abs(price.first - mergePrice.first) + price.second + mergePrice.second) bestPrice = std::abs(price.first - mergePrice.first) + price.second + mergePrice.second; actualPrice += bestPrice; if(result[price.first] != -1 && actualPrice > result[price.first]) break; } if(result[price.first] == -1 || actualPrice < result[price.first]) result[price.first] = actualPrice; } return result; } |