/* 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; } |
English