250706 공장들

Jongleee·2025년 7월 6일
0

TIL

목록 보기
951/970
static class Node {
	int to;
	long weight;
	Node next;

	Node(int to, long weight, Node next) {
		this.to = to;
		this.weight = weight;
		this.next = next;
	}
}

static final long INF = Long.MAX_VALUE;
static int n, logN;
static Node[] graph;
static int[][] parent;
static int[] depth, centroidParent, subtreeSize;
static long[] distFromRoot, minDist;
static boolean[] visited;
static Deque<Integer> updated;

public static void main(String[] args) throws IOException {
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer st = new StringTokenizer(br.readLine());
	n = Integer.parseInt(st.nextToken());
	int q = Integer.parseInt(st.nextToken());

	graph = new Node[n];
	for (int i = 1; i < n; i++) {
		st = new StringTokenizer(br.readLine());
		int u = Integer.parseInt(st.nextToken());
		int v = Integer.parseInt(st.nextToken());
		int w = Integer.parseInt(st.nextToken());
		graph[u] = new Node(v, w, graph[u]);
		graph[v] = new Node(u, w, graph[v]);
	}

	logN = (int) Math.ceil(Math.log(n) / Math.log(2));
	parent = new int[logN + 1][n+1];
	depth = new int[n+1];
	distFromRoot = new long[n+1];
	dfsForLCA(0, n, 0);

	for (int i = 1; i <= logN; i++) {
		for (int j = 0; j < n; j++) {
			parent[i][j] = parent[i - 1][parent[i - 1][j]];
		}
	}

	centroidParent = new int[n];
	subtreeSize = new int[n];
	visited = new boolean[n];
	minDist = new long[n];
	buildCentroidTree(0, n);

	updated = new ArrayDeque<>();
	StringBuilder sb = new StringBuilder();

	while (q-- > 0) {
		st = new StringTokenizer(br.readLine());
		int s = Integer.parseInt(st.nextToken());
		int t = Integer.parseInt(st.nextToken());

		while (!updated.isEmpty()) {
			minDist[updated.pollFirst()] = INF;
		}

		st = new StringTokenizer(br.readLine());
		for (int i = 0; i < s; i++) {
			int x = Integer.parseInt(st.nextToken());
			update(x);
		}

		long answer = INF;
		st = new StringTokenizer(br.readLine());
		for (int i = 0; i < t; i++) {
			int x = Integer.parseInt(st.nextToken());
			answer = Math.min(answer, query(x));
		}

		sb.append(answer).append('\n');
	}

	System.out.print(sb);
}

static void dfsForLCA(int current, int parentNode, long dist) {
	parent[0][current] = parentNode;
	depth[current] = parentNode == n ? 0 : depth[parentNode] + 1;
	distFromRoot[current] = parentNode == n ? 0 : distFromRoot[parentNode] + dist;
	for (Node next = graph[current]; next != null; next = next.next) {
		if (next.to != parentNode) {
			dfsForLCA(next.to, current, next.weight);
		}
	}
}

static int lca(int u, int v) {
	if (depth[u] < depth[v]) {
		int temp = u;
		u = v;
		v = temp;
	}

	for (int i = 0, diff = depth[u] - depth[v]; diff > 0; diff >>= 1, i++) {
		if ((diff & 1) == 1)
			u = parent[i][u];
	}

	if (u == v)
		return u;

	for (int i = logN; i >= 0; i--) {
		if (parent[i][u] != parent[i][v]) {
			u = parent[i][u];
			v = parent[i][v];
		}
	}

	return parent[0][u];
}

static long getDistance(int u, int v) {
	return distFromRoot[u] + distFromRoot[v] - 2 * distFromRoot[lca(u, v)];
}

static void update(int v) {
	for (int u = v; u != n; u = centroidParent[u]) {
		long dist = getDistance(u, v);
		if (dist < minDist[u]) {
			minDist[u] = dist;
			updated.addFirst(u);
		}
	}
}

static long query(int v) {
	long res = INF;
	for (int u = v; u != n; u = centroidParent[u]) {
		if (minDist[u] != INF) {
			res = Math.min(res, getDistance(u, v) + minDist[u]);
		}
	}
	return res == INF ? -1 : res;
}

static void buildCentroidTree(int current, int parentNode) {
	int centroid = getCentroid(current, -1, getSubtreeSize(current, -1) / 2);
	centroidParent[centroid] = parentNode;
	visited[centroid] = true;
	minDist[centroid] = INF;
	for (Node next = graph[centroid]; next != null; next = next.next) {
		if (!visited[next.to]) {
			buildCentroidTree(next.to, centroid);
		}
	}
}

static int getSubtreeSize(int current, int parentNode) {
	subtreeSize[current] = 1;
	for (Node next = graph[current]; next != null; next = next.next) {
		if (!visited[next.to] && next.to != parentNode) {
			subtreeSize[current] += getSubtreeSize(next.to, current);
		}
	}
	return subtreeSize[current];
}

static int getCentroid(int current, int parentNode, int threshold) {
	for (Node next = graph[current]; next != null; next = next.next) {
		if (!visited[next.to] && next.to != parentNode && subtreeSize[next.to] > threshold) {
			return getCentroid(next.to, current, threshold);
		}
	}
	return current;
}

출처:https://www.acmicpc.net/problem/11933

0개의 댓글