Pagini recente » Cod sursa (job #1349598) | Cod sursa (job #1914762) | Cod sursa (job #1206515) | Cod sursa (job #1910690) | Cod sursa (job #1739020)
#include <cstdio>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;
constexpr int maxN = 200000 + 1;
int to[maxN];
vector <int> adj[maxN];
vector <int> boundSons[maxN];
int cost[maxN];
int delta[maxN][2];
struct costCmp {
inline bool operator () ( const int &x, const int &y ) const {
return cost[x] < cost[y];
}
};
set <int, costCmp> sortedStack;
void getBounds( const int node, const int parent = -1 ) {
static int currentDelta = 0;
delta[node][0] = currentDelta++;
const set <int, costCmp> :: iterator iter = sortedStack.lower_bound(node);
if (iter == sortedStack.end())
to[node] = 0;
else
to[node] = *iter;
boundSons[to[node]].emplace_back(node);
sortedStack.insert(node);
for (const auto &son : adj[node])
if (son != parent)
getBounds(son, node);
sortedStack.erase(node);
delta[node][1] = currentDelta;
}
struct Event {
int b, e;
int cost;
inline bool operator <(const Event &other) const {
return e < other.e;
}
} E[maxN];
int dp[maxN]; // dp[i] = numarul maxim de noduri selectate din subarborele lui i, fara a alege noduri care obliga stramosi
int eventDp[maxN]; // eventDp[i] = numarul maxim de evenimente pe care le putem alege fara a se intersecta din primele i
void dfs( const int node, const int parent = -1 ) {
for (const auto &son : adj[node])
if (son != parent)
dfs(son, node);
int numEvents = 0;
for (const auto &boundSon : boundSons[node]) {
E[numEvents].b = delta[boundSon][0];
E[numEvents].e = delta[boundSon][1];
E[numEvents].cost = dp[boundSon];
numEvents++;
}
// u in subarb[v] si v in subarb[node]
// cost[u] > cost[v] si to[u] = to[v] = node => u si v nu pot fi alesi in acelasi timp
// costurile sunt disincte 2 cate 2 deci putem retine intervalul pe care este valabil un cost
// aflam submultimea de intervale disjuncte de suma de dp maxima
sort(E, E + numEvents);
for (int i = 0; i < numEvents; i++) {
int lo = -1, hi = i;
while (hi - lo > 1) {
int mid = (lo + hi) >> 1;
if (E[mid].e < E[i].b)
lo = mid;
else
hi = mid;
}
if ((lo == -1) || (eventDp[i - 1] > eventDp[lo] + E[i].cost)) {
if (eventDp[i - 1] > E[i].cost)
eventDp[i] = eventDp[i - 1];
else
eventDp[i] = E[i].cost;
}
else
eventDp[i] = eventDp[lo] + E[i].cost;
}
dp[node] = eventDp[numEvents - 1] + 1;
}
int main() {
freopen("guvern.in", "r", stdin);
freopen("guvern.out", "w", stdout);
int n;
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
adj[u].emplace_back(v);
adj[v].emplace_back(u);
}
adj[0].emplace_back(1);
cost[0] = 0x3f3f3f3f;
for (int i = 1; i <= n; i++)
scanf("%d", cost + i);
getBounds(0);
dfs(0);
printf("%d\n", dp[0] - 1);
return 0;
}