#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
/*
Let anc[u][x] be the x'th ancestor of u.
dp[u] =def= amount of time needed for message to be delivered from u to 1.
dp[1] =def= 0
dp[u] = min{S[u] + V[u]*dist(u, v) + dp[v] | v in anc[u]}
= min{S[u] + V[u]*(dist1[u] - dist1[v]) + dp[v] | v in anc[u]}
dp[u] min= S[u] + V[u]*dist1[u] + -dist1[v]*V[u] + dp[v]
a * x + b
*/
long long INF = 2'000'000'000'000'000'000;
vector<int> edge[100001], dist[100001]; //edges, weights of edges
vector<long long> S(100001, 0), V(100001, 0); //starting time, reciprocal speed
vector<long long> dist1(100001, 0);
int cht_anc[100001][19];
vector<int> prev_node(100001);
vector<long long> prev_dist(100001);
void dfs1(int u)
{
for(int i = 0; i < edge[u].size(); i++)
{
int v = edge[u][i];
long long d = dist[u][i];
if(prev_node[u] == v) continue;
prev_node[v] = u;
prev_dist[v] = d;
dist1[v] = dist1[u] + prev_dist[v];
dfs1(v);
}
}
vector<long long> a(100001), b(1000001);
vector<long long> dp(100001);
bool intersect_comp(int e1, int e2, long long x)
{ /*a[e1]*x + b[e1] = a[e2]*x + b[e2]
x_e = (b[e2] - b[e1])/(a[e1] - a[e2])
*/
return (b[e2] - b[e1]) < (a[e1] - a[e2])*x; //Be very careful with the sign.
}
bool line_intersect_comp(int e1, int e2, int f1, int f2)
{//intersect(e1, e2) < intersect(f1, f2)
if(e2 == 1) return 1;
return (b[e2] - b[e1])*(a[f1] - a[f2]) < (b[f2] - b[f1])*(a[e1] - a[e2]);
}
/*
i, i+1, L
Line i+2 is a good insertion if intersect(i, i+1) < intersect(i+1, i+2)
We need to binary search for the largest line i such that intersect(i-1, i) < intersect(i, L)
*/
void dfs2(int u)
{
for(int v: edge[u])
{
if(prev_node[u] == v) continue;
/*w is the ideal harbinger for the harbinger from v to go to
Using binary lifting, we search for the edge on which f(x) is maximised
*/
int w = u;
for(int e = 18; e >= 0; e--)
{
if(cht_anc[w][e] == 1) continue;
if(intersect_comp( prev_node[cht_anc[w][e]] , cht_anc[w][e], V[u] ) == 0)
w = cht_anc[w][e];
}
dp[v] = S[v] + V[v]*(dist1[v] - dist1[w]) + dp[w];
w = cht_anc[w][0];
dp[v] = min(dp[v], S[v] + V[v]*(dist1[v] - dist1[w]) + dp[w]);
a[v] = -dist1[v];
b[v] = dp[v];
w = u;
for(int e = 18; e >= 0; e--)
{
int temp = cht_anc[w][e];
if(line_intersect_comp(prev_node[temp], temp, temp, v))
continue;
w = temp;
}
if(!line_intersect_comp(prev_node[w], w, w, v))
w = cht_anc[w][0];
cht_anc[v][0] = w;
for(int e = 1; e <= 18; e++)
cht_anc[v][e] = cht_anc[ cht_anc[v][e-1] ][e-1];
dfs2(v);
}
}
int main()
{
int N;
cin >> N;
for(int j = 1; j <= N-1; j++)
{
int u, v, d;
cin >> u >> v >> d;
edge[u].push_back(v);
dist[u].push_back(d);
edge[v].push_back(u);
dist[v].push_back(d);
}
for(int i = 2; i <= N; i++)
cin >> S[i] >> V[i];
prev_node[1] = 1;
prev_dist[1] = 0;
dfs1(1);
// for(int i = 1; i <= N; i++)
// {
// cerr << "i = " << i << ": ";
// cerr << S[i] << ' ' << V[i] << ' ' << dist1[i] << " " << prev_node[i] << ' ' << prev_dist[i] << '\n';
// }
dp[1] = 0;
for(int e = 0; e <= 18; e++)
cht_anc[1][e] = 1;
V[1] = S[1] = 0;
dfs2(1);
for(int i = 2; i <= N; i++) cout << dp[i] << ' ';
cout << '\n';
}
Compilation message
harbingers.cpp: In function 'void dfs1(int)':
harbingers.cpp:29:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
29 | for(int i = 0; i < edge[u].size(); i++)
| ~~^~~~~~~~~~~~~~~~
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Incorrect |
11 ms |
17868 KB |
Output isn't correct |
2 |
Incorrect |
16 ms |
18572 KB |
Output isn't correct |
3 |
Incorrect |
146 ms |
28868 KB |
Output isn't correct |
4 |
Runtime error |
232 ms |
34032 KB |
Memory limit exceeded |
5 |
Runtime error |
281 ms |
39156 KB |
Memory limit exceeded |
6 |
Runtime error |
388 ms |
44028 KB |
Memory limit exceeded |
7 |
Incorrect |
201 ms |
31772 KB |
Output isn't correct |
8 |
Runtime error |
417 ms |
38124 KB |
Memory limit exceeded |
9 |
Runtime error |
392 ms |
40288 KB |
Memory limit exceeded |
10 |
Runtime error |
360 ms |
39108 KB |
Memory limit exceeded |