abcdeffa's Blog

当局者迷,旁观者清。

0%

GMOJ S6583 【disruption】

Description

给你一个有 $n$ 个点的树,以及 $m$ 条额外边,现在请你求出任意一条树边被删去后能够使这个图变为树的权值最小的一条额外边的边权,若不存在则输出“-1”。

Solution

显然当某一条树边被删去后能够用从点 $x$ 到点 $y$ 的额外边连上然后成树 当且仅当 这条树边是在原树上从点 $x$ 到点 $y$ 的一条边。

反之亦然。

因此可以用每一条额外边来更新树边的答案,用 树链剖分 即可。

Code

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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#include <cstdio>
#define INF 2147483647
#define maxN 100010
struct tree{ int min, tag; } a[maxN << 2];
struct edge{ int x, y, c, g; } b[maxN << 1];
int len = 0, n = 0, m = 0;
int Ans[maxN];
int number[maxN], top[maxN];
int f[maxN][20], size[maxN], son[maxN], dep[maxN], bh[maxN], h[maxN];
int Min (int x, int y)
{
return x < y ? x : y;
}
void build (int now, int l, int r)
{
a[now].min = a[now].tag = INF;
if(l < r)
{
int mid = (l + r) >> 1;
build(now << 1, l, mid);
build(now << 1 | 1, mid + 1, r);
}
}
void ins (int x, int y)
{
len++;
b[len].x = x;
b[len].y = y;
b[len].c = (len + 1) / 2;
b[len].g = h[x];
h[x] = len;
}
void dfs1 (int x)
{
for(int i = h[x];i;i = b[i].g)
{
int y = b[i].y;
if(!dep[y])
{
f[y][0] = x;
bh[y] = b[i].c;
dep[y] = dep[x] + 1;
dfs1(y);
size[x] += size[y];
if(size[y] > size[son[x]])
{
son[x] = y;
}
}
}
size[x]++;
}
void dfs2 (int x)
{
number[x] = ++number[0];
if(son[x])
{
top[son[x]] = top[x];
dfs2(son[x]);
}
for(int i = h[x];i;i = b[i].g)
{
int y = b[i].y;
if(dep[x] + 1 == dep[y] && y != son[x])
{
top[y] = y;
dfs2(y);
}
}
}
void pushdown (int now, int l, int r)
{
if(a[now].tag != INF)
{
if(l < r)
{
a[now << 1].min = Min(a[now << 1].min, a[now].tag);
a[now << 1 | 1].min = Min(a[now << 1 | 1].min, a[now].tag);
a[now << 1].tag = Min(a[now << 1].tag, a[now].tag);
a[now << 1 | 1].tag = Min(a[now << 1 | 1].tag, a[now].tag);
}
a[now].tag = INF;
}
}
void change (int now, int l, int r, int L, int R, int x)
{
if(l == L && r == R)
{
a[now].tag = Min(a[now].tag, x);
a[now].min = Min(a[now].min, x);
return ;
}
pushdown(now, l, r);
int mid = (l + r) >> 1;
if(R <= mid)
{
change(now << 1, l, mid, L, R, x);
}
else if(mid + 1 <= L)
{
change(now << 1 | 1, mid + 1, r, L, R, x);
}
else
{
change(now << 1, l, mid, L, mid, x);
change(now << 1 | 1, mid + 1, r, mid + 1, R, x);
}
a[now].min = Min(a[now << 1].min, a[now << 1 | 1].min);
}
int query (int now, int l, int r, int L, int R)
{
if(l == L && r == R)
{
return a[now].min;
}
pushdown(now, l, r);
int mid = (l + r) >> 1;
if(R <= mid)
{
return query(now << 1, l, mid, L, R);
}
else if(mid + 1 <= L)
{
return query(now << 1 | 1, mid + 1, r, L, R);
}
else
{
int A = query(now << 1, l, mid, L, mid);
int B = query(now << 1 | 1, mid + 1, r, mid + 1, R);
return Min(A, B);
}
}
int lca (int x, int y)
{
if(dep[x] < dep[y])
{
int t = x;
x = y;
y = t;
}
for(int i = 19;i >= 0; i--)
{
if(f[x][i] && dep[f[x][i]] >= dep[y])
{
x = f[x][i];
}
}
if(x == y)
{
return x;
}
for(int i = 19;i >= 0; i--)
{
if(f[x][i] && f[y][i] && f[x][i] != f[y][i])
{
x = f[x][i];
y = f[y][i];
}
}
return f[x][0];
}
void work (int x, int y, int c)
{
int LCA = lca(x, y);
int now = query(1, 1, n, number[LCA], number[LCA]);
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]])
{
int t = x;
x = y;
y = t;
}
if(top[x] == LCA)
{
if(top[x] != x)
{
change(1, 1, n, number[top[x]] + 1, number[x], c);
}
}
else
{
change(1, 1, n, number[top[x]], number[x], c);
}
x = f[top[x]][0];
}
if(dep[x] > dep[y])
{
int t = x;
x = y;
y = t;
}
if(x != y)
{
if(x == LCA)
{
change(1, 1, n, number[x] + 1, number[y], c);
}
else
{
change(1, 1, n, number[x], number[y], c);
}
}
}
int main ()
{
scanf("%d %d", &n, &m);
for(int i = 1;i < n; i++)
{
int x = 0, y = 0;
scanf("%d %d", &x, &y);
ins(x, y);
ins(y, x);
}
int root = 1;
dep[root] = 1;
dfs1(root);
top[root] = root;
for(int j = 1;j <= 19; j++)
{
for(int i = 1;i <= n; i++)
{
f[i][j] = f[f[i][j - 1]][j - 1];
}
}
dfs2(root);
build(1, 1, n);
for(int i = 1;i <= m; i++)
{
int x = 0, y = 0, c = 0;
scanf("%d %d %d", &x, &y, &c);
work(x, y, c);
}
for(int i = 2;i <= n; i++)
{
Ans[bh[i]] = query(1, 1, n, number[i], number[i]);
}
for(int i = 1;i < n; i++)
{
printf("%d\n", Ans[i] != 2147483647 ? Ans[i] : -1);
}
return 0;
}