Skip to content

Commit b50d16f

Browse files
committed
modify code
1 parent 8b460eb commit b50d16f

File tree

2 files changed

+393
-1
lines changed

2 files changed

+393
-1
lines changed

src/class183/Code03_Race1.java

Lines changed: 261 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,267 @@
11
package class183;
22

3-
// 边最少的权值和为k的路径,java版
3+
// 权值和为k的路径的最少边数,java版
44
// 测试链接 : https://www.luogu.com.cn/problem/P4149
5+
// 提交以下的code,提交时请把类名改成"Main",可以通过所有测试用例
6+
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.io.OutputStreamWriter;
10+
import java.io.PrintWriter;
11+
import java.util.Arrays;
12+
513
public class Code03_Race1 {
614

15+
public static int MAXN = 200001;
16+
public static int MAXK = 1000001;
17+
public static int INF = 1000000001;
18+
public static int n, k, total;
19+
20+
public static int[] head = new int[MAXN];
21+
public static int[] nxt = new int[MAXN << 1];
22+
public static int[] to = new int[MAXN << 1];
23+
public static int[] weight = new int[MAXN << 1];
24+
public static int cntg;
25+
26+
public static boolean[] vis = new boolean[MAXN];
27+
public static int[] siz = new int[MAXN];
28+
public static int[] maxPart = new int[MAXN];
29+
public static int centroid;
30+
31+
public static int[] sumArr = new int[MAXN];
32+
public static int[] edgeArr = new int[MAXN];
33+
public static int cnta;
34+
35+
public static int[] dp = new int[MAXK];
36+
37+
// java的实现,getCentroid方法、getPath方法改成迭代才能通过,C++的实现不需要改动
38+
// 讲解118,讲了如何把递归函数改成迭代
39+
public static int[][] stack = new int[MAXN][5];
40+
public static int stacksize, u, f, sum, edge, e;
41+
42+
public static void push(int u, int f, int sum, int edge, int e) {
43+
stack[stacksize][0] = u;
44+
stack[stacksize][1] = f;
45+
stack[stacksize][2] = sum;
46+
stack[stacksize][3] = edge;
47+
stack[stacksize][4] = e;
48+
stacksize++;
49+
}
50+
51+
public static void pop() {
52+
--stacksize;
53+
u = stack[stacksize][0];
54+
f = stack[stacksize][1];
55+
sum = stack[stacksize][2];
56+
edge = stack[stacksize][3];
57+
e = stack[stacksize][4];
58+
}
59+
60+
public static void addEdge(int u, int v, int w) {
61+
nxt[++cntg] = head[u];
62+
to[cntg] = v;
63+
weight[cntg] = w;
64+
head[u] = cntg;
65+
}
66+
67+
// 找重心的递归版,java会爆栈,C++可以通过
68+
public static void getCentroid1(int u, int fa) {
69+
siz[u] = 1;
70+
maxPart[u] = 0;
71+
for (int e = head[u]; e > 0; e = nxt[e]) {
72+
int v = to[e];
73+
if (v != fa && !vis[v]) {
74+
getCentroid1(v, u);
75+
siz[u] += siz[v];
76+
maxPart[u] = Math.max(siz[v], maxPart[u]);
77+
}
78+
}
79+
maxPart[u] = Math.max(maxPart[u], total - siz[u]);
80+
if (centroid == 0 || maxPart[u] < maxPart[centroid]) {
81+
centroid = u;
82+
}
83+
}
84+
85+
// 找重心的迭代版
86+
public static void getCentroid2(int cur, int fa) {
87+
stacksize = 0;
88+
push(cur, fa, 0, 0, -1);
89+
while (stacksize > 0) {
90+
pop();
91+
if (e == -1) {
92+
siz[u] = 1;
93+
maxPart[u] = 0;
94+
e = head[u];
95+
} else {
96+
e = nxt[e];
97+
}
98+
if (e != 0) {
99+
push(u, f, 0, 0, e);
100+
int v = to[e];
101+
if (v != f && !vis[v]) {
102+
push(to[e], u, 0, 0, -1);
103+
}
104+
} else {
105+
for (int ei = head[u]; ei > 0; ei = nxt[ei]) {
106+
int v = to[ei];
107+
if (v != f && !vis[v]) {
108+
siz[u] += siz[v];
109+
maxPart[u] = Math.max(siz[v], maxPart[u]);
110+
}
111+
}
112+
maxPart[u] = Math.max(maxPart[u], total - siz[u]);
113+
if (centroid == 0 || maxPart[u] < maxPart[centroid]) {
114+
centroid = u;
115+
}
116+
}
117+
}
118+
}
119+
120+
// 收集路径的递归版,java会爆栈,C++可以通过
121+
public static void getPath1(int u, int fa, int sum, int edge) {
122+
if (sum > k) {
123+
return;
124+
}
125+
sumArr[++cnta] = sum;
126+
edgeArr[cnta] = edge;
127+
for (int e = head[u]; e > 0; e = nxt[e]) {
128+
int v = to[e];
129+
if (v != fa && !vis[v]) {
130+
getPath1(v, u, sum + weight[e], edge + 1);
131+
}
132+
}
133+
}
134+
135+
// 收集路径的迭代版
136+
public static void getPath2(int cur, int fa, int psum, int pedge) {
137+
stacksize = 0;
138+
push(cur, fa, psum, pedge, -1);
139+
while (stacksize > 0) {
140+
pop();
141+
if (e == -1) {
142+
if (sum > k) {
143+
continue;
144+
}
145+
sumArr[++cnta] = sum;
146+
edgeArr[cnta] = edge;
147+
e = head[u];
148+
} else {
149+
e = nxt[e];
150+
}
151+
if (e != 0) {
152+
push(u, f, sum, edge, e);
153+
int v = to[e];
154+
if (v != f && !vis[v]) {
155+
push(to[e], u, sum + weight[e], edge + 1, -1);
156+
}
157+
}
158+
}
159+
}
160+
161+
public static int calc(int u) {
162+
int ans = INF;
163+
cnta = 0;
164+
dp[0] = 0;
165+
for (int e = head[u]; e > 0; e = nxt[e]) {
166+
int v = to[e];
167+
if (!vis[v]) {
168+
int tmp = cnta;
169+
// getPath1(v, u, weight[e], 1);
170+
getPath2(v, u, weight[e], 1);
171+
for (int i = tmp + 1; i <= cnta; i++) {
172+
ans = Math.min(ans, dp[k - sumArr[i]] + edgeArr[i]);
173+
}
174+
for (int i = tmp + 1; i <= cnta; i++) {
175+
dp[sumArr[i]] = Math.min(dp[sumArr[i]], edgeArr[i]);
176+
}
177+
}
178+
}
179+
for (int i = 1; i <= cnta; i++) {
180+
dp[sumArr[i]] = INF;
181+
}
182+
return ans;
183+
}
184+
185+
public static int compute(int u) {
186+
int ans = INF;
187+
vis[u] = true;
188+
ans = Math.min(ans, calc(u));
189+
for (int e = head[u]; e > 0; e = nxt[e]) {
190+
int v = to[e];
191+
if (!vis[v]) {
192+
total = siz[v];
193+
centroid = 0;
194+
// getCentroid1(v, 0);
195+
getCentroid2(v, 0);
196+
ans = Math.min(ans, compute(centroid));
197+
}
198+
}
199+
return ans;
200+
}
201+
202+
public static void main(String[] args) throws Exception {
203+
FastReader in = new FastReader(System.in);
204+
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
205+
n = in.nextInt();
206+
k = in.nextInt();
207+
for (int i = 1, u, v, w; i < n; i++) {
208+
u = in.nextInt() + 1;
209+
v = in.nextInt() + 1;
210+
w = in.nextInt();
211+
addEdge(u, v, w);
212+
addEdge(v, u, w);
213+
}
214+
total = n;
215+
centroid = 0;
216+
// getCentroid1(1, 0);
217+
getCentroid2(1, 0);
218+
Arrays.fill(dp, INF);
219+
int ans = compute(centroid);
220+
if (ans == INF) {
221+
ans = -1;
222+
}
223+
out.println(ans);
224+
out.flush();
225+
out.close();
226+
}
227+
228+
// 读写工具类
229+
static class FastReader {
230+
private final byte[] buffer = new byte[1 << 20];
231+
private int ptr = 0, len = 0;
232+
private final InputStream in;
233+
234+
FastReader(InputStream in) {
235+
this.in = in;
236+
}
237+
238+
private int readByte() throws IOException {
239+
if (ptr >= len) {
240+
len = in.read(buffer);
241+
ptr = 0;
242+
if (len <= 0)
243+
return -1;
244+
}
245+
return buffer[ptr++];
246+
}
247+
248+
int nextInt() throws IOException {
249+
int c;
250+
do {
251+
c = readByte();
252+
} while (c <= ' ' && c != -1);
253+
boolean neg = false;
254+
if (c == '-') {
255+
neg = true;
256+
c = readByte();
257+
}
258+
int val = 0;
259+
while (c > ' ' && c != -1) {
260+
val = val * 10 + (c - '0');
261+
c = readByte();
262+
}
263+
return neg ? -val : val;
264+
}
265+
}
266+
7267
}

0 commit comments

Comments
 (0)