Skip to content

Commit eb5cd8c

Browse files
authored
Merge pull request #1700 from AlgorithmWithGod/khj20006
[20251217] BOJ / D3 / Vjeverice / 권혁준
2 parents fc66337 + 9f98dfa commit eb5cd8c

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
```java
2+
import java.util.*;
3+
import java.io.*;
4+
5+
public class Main {
6+
7+
static final int INF = (int)1e9 + 7;
8+
9+
static BufferedReader br;
10+
static BufferedWriter bw;
11+
static StringTokenizer st;
12+
13+
static int N, M, Q;
14+
static int[][] edges;
15+
static List<int[]>[] graph, tree;
16+
static int[] dep;
17+
static int[] root;
18+
static int[][] par, max, queries;
19+
static BitSet used;
20+
static int[] alternativeCost;
21+
22+
public static int find(int x) { return x == root[x] ? x : (root[x] = find(root[x])); }
23+
24+
public static void main(String[] args) throws Exception {
25+
26+
input();
27+
solve();
28+
29+
}
30+
31+
public static void input() throws Exception {
32+
br = new BufferedReader(new InputStreamReader(System.in));
33+
34+
st = new StringTokenizer(br.readLine());
35+
N = Integer.parseInt(st.nextToken());
36+
M = Integer.parseInt(st.nextToken());
37+
38+
edges = new int[M+1][];
39+
graph = new List[N+1];
40+
tree = new List[N+1];
41+
for(int i=1;i<=N;i++) {
42+
graph[i] = new ArrayList<>();
43+
tree[i] = new ArrayList<>();
44+
}
45+
46+
for(int i=1;i<=M;i++) {
47+
st = new StringTokenizer(br.readLine());
48+
int a = Integer.parseInt(st.nextToken());
49+
int b = Integer.parseInt(st.nextToken());
50+
int c = Integer.parseInt(st.nextToken());
51+
edges[i] = new int[]{a,b,c};
52+
graph[a].add(new int[]{b,c});
53+
graph[b].add(new int[]{a,c});
54+
}
55+
56+
Q = Integer.parseInt(br.readLine());
57+
queries = new int[Q][];
58+
for(int i=0;i<Q;i++) {
59+
st = new StringTokenizer(br.readLine());
60+
queries[i] = new int[]{Integer.parseInt(st.nextToken()), Integer.parseInt(st.nextToken())};
61+
}
62+
63+
br.close();
64+
}
65+
66+
public static void solve() throws Exception {
67+
// Construct MST
68+
root = new int[N+1];
69+
for(int i=1;i<=N;i++) root[i] = i;
70+
71+
List<int[]> edgesTemp = new ArrayList<>();
72+
for(int i=1;i<=M;i++) edgesTemp.add(new int[]{edges[i][0], edges[i][1], edges[i][2], i});
73+
Collections.sort(edgesTemp, (a,b) -> a[2]-b[2]);
74+
75+
int mstCost = 0;
76+
used = new BitSet(N+1);
77+
for(int[] edge : edgesTemp) {
78+
int a = edge[0], b = edge[1], c = edge[2], n = edge[3];
79+
int x = find(a), y = find(b);
80+
if(x == y) continue;
81+
mstCost += c;
82+
used.set(n);
83+
root[x] = y;
84+
tree[a].add(new int[]{b,c});
85+
tree[b].add(new int[]{a,c});
86+
}
87+
88+
// Construct sparse table
89+
dep = new int[N+1];
90+
par = new int[N+1][17];
91+
max = new int[N+1][17];
92+
dfs(1,0,0);
93+
94+
for(int k=1;k<17;k++) for(int i=1;i<=N;i++) {
95+
par[i][k] = par[par[i][k-1]][k-1];
96+
max[i][k] = Math.max(max[i][k-1], max[par[i][k-1]][k-1]);
97+
}
98+
99+
// Find alternative cost
100+
root = new int[N+1];
101+
for(int i=1;i<=N;i++) root[i] = i;
102+
alternativeCost = new int[N+1];
103+
Arrays.fill(alternativeCost, INF);
104+
105+
for(int[] edge : edgesTemp) if(!used.get(edge[3])) {
106+
int a = edge[0], b = edge[1], c = edge[2];
107+
int x = find(a), y = find(b);
108+
while(x != y) {
109+
if(dep[x] > dep[y]) {
110+
alternativeCost[x] = c;
111+
x = par[x][0];
112+
root[x] = find(par[x][0]);
113+
x = find(x);
114+
}
115+
else {
116+
alternativeCost[y] = c;
117+
y = par[y][0];
118+
root[y] = find(par[y][0]);
119+
y = find(y);
120+
}
121+
}
122+
}
123+
124+
// Solve queries
125+
bw = new BufferedWriter(new OutputStreamWriter(System.out));
126+
bw.write(mstCost + "\n");
127+
128+
for(int[] query : queries) {
129+
int a = edges[query[0]][0];
130+
int b = edges[query[0]][1];
131+
int c = query[1];
132+
133+
if(used.get(query[0])) {
134+
int child = a == par[b][0] ? b : a;
135+
bw.write((mstCost - edges[query[0]][2] + Math.min(c, alternativeCost[child])) + "\n");
136+
}
137+
else {
138+
int mx = 0, diff = Math.abs(dep[a] - dep[b]);
139+
for(int k=0;k<17;k++) if((diff & (1<<k)) != 0) {
140+
if(dep[a] > dep[b]) {
141+
mx = Math.max(mx, max[a][k]);
142+
a = par[a][k];
143+
}
144+
else {
145+
mx = Math.max(mx, max[b][k]);
146+
b = par[b][k];
147+
}
148+
}
149+
150+
for(int k=16;k>=0;k--) if(par[a][k] != par[b][k]) {
151+
mx = Math.max(mx, Math.max(max[a][k], max[b][k]));
152+
a = par[a][k];
153+
b = par[b][k];
154+
}
155+
if(a != b) {
156+
mx = Math.max(max[a][0], max[b][0]);
157+
}
158+
159+
bw.write(Math.min(mstCost, mstCost + c - mx) + "\n");
160+
}
161+
162+
}
163+
164+
bw.close();
165+
}
166+
167+
public static void dfs(int n, int p, int d) {
168+
par[n][0] = p;
169+
dep[n] = d;
170+
for(int[] edge : tree[n]) if(edge[0] != p) {
171+
dfs(edge[0], n, d+1);
172+
max[edge[0]][0] = edge[1];
173+
}
174+
}
175+
176+
}
177+
178+
```

0 commit comments

Comments
 (0)