250718 Olympic Bus

Jongleee·2025년 7월 18일
0

TIL

목록 보기
963/970
private static final int N = 207, M = 100007;
private static final long INF = (long) 1e18;

private static class GraphState {
	long[] dist = new long[N];
	boolean[] inPath = new boolean[M];
}

private static int n, m, edgeCount = 1;
private static int[] head = new int[N], to = new int[M], next = new int[M];
private static long[] cost = new long[M], delay = new long[M];
private static boolean[] isUsed = new boolean[M];
private static long currentTotal, answer = INF;
private static GraphState g1 = new GraphState(), gn = new GraphState(), gt1 = new GraphState(),
		gtn = new GraphState();

public static void main(String[] args) throws IOException {
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	StringTokenizer st;

	st = new StringTokenizer(br.readLine());
	n = Integer.parseInt(st.nextToken());
	m = Integer.parseInt(st.nextToken());

	for (int i = 1; i <= m; i++) {
		st = new StringTokenizer(br.readLine());
		int x = Integer.parseInt(st.nextToken());
		int y = Integer.parseInt(st.nextToken());
		int c = Integer.parseInt(st.nextToken());
		int d = Integer.parseInt(st.nextToken());
		addEdge(x, y, c, d);
	}

	currentTotal += dijkstra(1, n, isUsed, g1);
	currentTotal += dijkstra(n, 1, isUsed, gn);
	answer = Math.min(answer, currentTotal);

	flipEdges();
	dijkstra(1, n, isUsed, gt1);
	dijkstra(n, 1, isUsed, gtn);
	flipEdges();

	for (int i = 2; i <= edgeCount; i += 2) {
		answer = Math.min(answer, simulateEdgeRemoval(i));
	}

	System.out.println(answer == INF ? -1 : answer);
}

private static void addEdge(int x, int y, int c, int d) {
	to[++edgeCount] = y;
	next[edgeCount] = head[x];
	head[x] = edgeCount;
	cost[edgeCount] = c;
	delay[edgeCount] = d;
	isUsed[edgeCount] = true;

	to[++edgeCount] = x;
	next[edgeCount] = head[y];
	head[y] = edgeCount;
	cost[edgeCount] = c;
	delay[edgeCount] = d;
	isUsed[edgeCount] = false;
}

private static long dijkstra(int start, int end, boolean[] used, GraphState state) {
	long[][] minCost = new long[N][N];
	int[][] edgeId = new int[N][N];
	for (int[] row : edgeId)
		Arrays.fill(row, -1);
	for (long[] row : minCost)
		Arrays.fill(row, INF);

	for (int x = 1; x <= n; x++) {
		for (int i = head[x]; i > 0; i = next[i]) {
			if (!used[i])
				continue;
			int y = to[i];
			if (minCost[x][y] > cost[i]) {
				minCost[x][y] = cost[i];
				edgeId[x][y] = i;
			}
		}
	}

	long[] dist = new long[N];
	boolean[] visited = new boolean[N];
	int[] trace = new int[N];
	Arrays.fill(dist, INF);
	Arrays.fill(trace, -1);
	dist[start] = 0;

	for (int i = 1; i <= n; i++) {
		int u = -1;
		for (int j = 1; j <= n; j++) {
			if (!visited[j] && (u == -1 || dist[j] < dist[u])) {
				u = j;
			}
		}
		if (u == -1)
			break;
		visited[u] = true;

		for (int v = 1; v <= n; v++) {
			if (visited[v])
				continue;
			if (minCost[u][v] < INF && dist[v] > dist[u] + minCost[u][v]) {
				dist[v] = dist[u] + minCost[u][v];
				trace[v] = edgeId[u][v];
			}
		}
	}

	System.arraycopy(dist, 0, state.dist, 0, N);
	Arrays.fill(state.inPath, false);
	for (int v = end; v != start && trace[v] != -1;) {
		state.inPath[trace[v]] = true;
		v = to[trace[v] ^ 1];
	}

	return dist[end];
}

private static void flipEdges() {
	for (int i = 2; i <= edgeCount; i++) {
		isUsed[i] ^= true;
	}
}

private static long simulateEdgeRemoval(int i) {
	long temp = delay[i];
	isUsed[i] = false;
	isUsed[i ^ 1] = true;

	if (g1.inPath[i]) {
		temp += dijkstra(1, n, isUsed, new GraphState());
	} else {
		long candidate = cost[i] + g1.dist[to[i]];
		if (gtn.inPath[i]) {
			candidate += dijkstra(to[i ^ 1], n, isUsed, new GraphState());
		} else {
			candidate += gtn.dist[to[i ^ 1]];
		}
		temp += Math.min(g1.dist[n], candidate);
	}

	if (gn.inPath[i]) {
		temp += dijkstra(n, 1, isUsed, new GraphState());
	} else {
		long candidate = cost[i] + gn.dist[to[i]];
		if (gt1.inPath[i]) {
			candidate += dijkstra(to[i ^ 1], 1, isUsed, new GraphState());
		} else {
			candidate += gt1.dist[to[i ^ 1]];
		}
		temp += Math.min(gn.dist[1], candidate);
	}

	isUsed[i] = true;
	isUsed[i ^ 1] = false;
	return temp;
}

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

0개의 댓글