NOIP 2015
Day2
План T3 транспорт
Смысл проблем: есть \ (п \) точек дерева, каждая сторона имеет длину, м задается путь дерева, вы можете выбрать ребро, его длина изменяется на 0, это требуется самый длинный путь м Что такое кратчайшее
\ (П, т \ е. 3 \ times10. 5 ^ \) , длина стороны не более чем \ (1000 \)
Решение:
\ (1 \) двоичный ответ, длина начального пересечения перерасхода, если пересечение равно 0, никакого решения, или выбрана из самой длинной стороны перекрестка
\ (2 \) разность дерева пересечения (-1 конечная точка $ \ (\) ДМС $ + 2)
Сложность Время: \ (O (Nlog ^ 2n) \)
\ (1 \) рассмотрим пересечение двадцать-две пути, то он должен быть найден в обоих концах пути \ (4 \) путь в (название самой глубокой два месяца ДМС LCA может сделать это, а также рассмотреть другие вопросы \ (4 \) , где нравится) -м перекрывается LCA.
\ (2 \) , чтобы сделать это нашли дихотомии не очень полезно, вы можете положить на стороне убывающем порядке, а затем пересечения, то ответ перечислить, если пересечение пусто или длинная длина не хватает, а на выходе ответить. Это может быть \ (RMQ \) Оптимизация запроса \ (ЛКА \) .
Сложность Время: \ (O (NlogN) \) слышал ряд методов может быть магия (RMQ \) \ предварительной обработки для оптимизации \ (O (n-) \) , общая сложность времени достигает \ (O ( п) \)
Для первого \ (O (Nlog ^ 2n) \) решение, мы обнаружили , могут быть предварительно обработаны непосредственно LCA каждую пару, так что временная сложность будет сведена к \ (O (NlogN) \)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 300100
#define RE register
int n, m;
int st[maxn], ed[maxn], len[maxn];
int fir[maxn], nxt[maxn * 2], vv[maxn * 2], edge[maxn * 2];
int tot = 0;
int read()
{
int ret = 0;
char ch = getchar();
while(ch < '0' || ch > '9')
{
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
ret = ret * 10 + ch - '0';
ch = getchar();
}
return ret;
}
void add(int u, int v, int w)
{
nxt[++tot] = fir[u];
fir[u] = tot;
vv[tot] = v;
edge[tot] = w;
}
int dep[maxn], f[maxn][25], g[maxn][25];
void Deal_first(int u, int fa)
{
// printf("u = %d fa = %d\n", u, fa);
dep[u] = dep[fa] + 1;
for(RE int i = 0; i <= 19; i++)
{
f[u][i + 1] = f[f[u][i]][i];
g[u][i + 1] = g[u][i] + g[f[u][i]][i];
}
for(RE int i = fir[u]; i; i = nxt[i])
{
int v = vv[i];
if(v == fa) continue;
f[v][0] = u;
g[v][0] = edge[i];
Deal_first(v, u);
}
}
int LCA(int x, int y, int &dis)
{
if(dep[x] < dep[y]) swap(x, y);
for(RE int i = 20; i >= 0; i--)
{
if(dep[f[x][i]] >= dep[y])
{
dis += g[x][i];
// printf("g[x][i] = %d\n", g[x][i]);
x = f[x][i];
}
// printf("x = %d y = %d\n", x, y);
if(x == y)
{
return x;
}
}
for(RE int i = 20; i >= 0; i--)
{
if(f[x][i] != f[y][i])
{
dis += g[x][i];
dis += g[y][i];
x = f[x][i];
y = f[y][i];
// printf("x = %d y = %d\n", x, y);
}
}
dis += (g[x][0] + g[y][0]);
return f[x][0];
}
int val[maxn], dp[maxn * 2], from[maxn], lc[maxn];
void dfs(int u, int fa)
{
dp[from[u]] += val[u];
for(RE int i = fir[u]; i; i = nxt[i])
{
int v = vv[i];
if(v == fa) continue;
from[v] = i;
dfs(v, u);
dp[from[u]] += dp[from[v]];
}
}
int lenth;
int check(int x)
{
memset(val, 0, sizeof(val));
memset(dp, 0, sizeof(dp));
int cnt = 0;
for(RE int i = 1; i <= m; i++)
{
if(len[i] > x)
{
cnt++;
int u = st[i], v = ed[i];
int xx = 0;
val[u] += 1; val[v] += 1;
val[lc[i]] -= 2;
}
// else break;
}
dfs(1, 0);
int maxx = -1;
for(RE int i = 1; i <= tot; i++)
{
// printf("dp[%d] = %d ", i, dp[i]);
if(dp[i] >= cnt)
{
maxx = max(maxx, edge[i]);
}
}
// printf("\n");
// printf("x = %d cnt = %d maxx = %d\n", x, cnt, maxx);
if(!cnt) return 1;
if(maxx == -1 || lenth - maxx > x) return 0;
return 1;
}
bool cmp(int x, int y)
{
return x > y;
}
int main()
{
n = read(); m = read();
for(RE int i = 1; i < n; i++)
{
int u, v, w;
u = read(); v = read(); w = read();
add(u, v, w); add(v, u, w);
}
for(RE int i = 1; i <= m; i++)
{
st[i] = read(); ed[i] = read();
}
Deal_first(1, 0);
for(RE int i = 1; i <= m; i++)
{
int dis = 0;
int fa = LCA(st[i], ed[i], dis);
len[i] = dis; lenth = max(lenth, len[i]);
lc[i] = fa;
// printf("u = %d v = %d fa = %d\n", st[i], ed[i], fa);
//len[i] = dep[st[i]] + dep[ed[i]] - dep[LCA(st[i], ed[i])] * 2;
}
// sort(len + 1, len + m + 1, cmp);
// for(int i = 1; i <= m; i++) printf("len[%d] = %d\n", i, len[i]);
int l = 0, r = 3e8, ans = 0;
while(l <= r)
{
int mid = (l + r) >> 1;
if(check(mid) == 1)
{
ans = mid;
r = mid - 1;
}
else l = mid + 1;
}
printf("%d\n", ans);
return 0;
}