Home BOJ. ATM (4013)
Post
Cancel

BOJ. ATM (4013)

[Link] https://www.acmicpc.net/problem/4013


Step 1. get SCC

Step 2.

Method 1

Tarjan is DFS SCC => update dp from biggest idx to lower

1
2
3
4
5
for(int i = groupIdx - 1; i >= 0; i--) {
	for(int ge : sccEdges[i]) {
		dp[ge] = Math.max(dp[ge], dp[i] + money[ge]);
	}
}

Method 2

SCC => DAG(Directed Acyclic Graph) => update dp in order of Topological sort

Method 3

Similar to Method 2, use Dijkstra


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
import java.util.*;
import java.io.*;

public class Main {
	static BufferedReader br;
	// static StringBuilder sb = new StringBuilder();
	static ArrayList<Integer>[] edges;
	static int[] parent, group;
	static boolean[] finish;
	static int sccIdx = 1, groupIdx = 0;
	static Stack<Integer> stack = new Stack<>();

	public static void main(String[] args) throws IOException {
		br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		int[] arr = getArr();
		int n = arr[0], m = arr[1];
		edges = new ArrayList[n];
		parent = new int[n];
		finish = new boolean[n];
		group = new int[n];
		Arrays.fill(group, -1);

		for(int i = 0; i < n; i++) edges[i] = new ArrayList<>();

		for(int i = 0; i < m; i++) {
			arr = getArr();
			int a = arr[0] - 1, b = arr[1] - 1;
			edges[a].add(b);
		}


		int[] moneyTmp = new int[n];
		for(int i = 0; i < n; i++) moneyTmp[i] = toi(br.readLine());

		arr = getArr();
		int s = arr[0] - 1, p = arr[1];
		scc(s);

		ArrayList<Integer>[] sccEdges = new ArrayList[sccIdx];
		for(int i = 0; i < groupIdx; i++) sccEdges[i] = new ArrayList<>();
		boolean[] restaurant = new boolean[groupIdx];
		long[] dp = new long[groupIdx];
		long[] money = new long[groupIdx];

		arr = getArr();
		for(int e: arr) {
			if(group[e - 1] == -1) continue;
			restaurant[group[e - 1]] = true;
		}

		for(int i = 0; i < n; i++) {
			if(group[i] == -1) continue;
			money[group[i]] += moneyTmp[i];
			for(int e: edges[i]) {
				if(group[e] == group[i]) continue;
				sccEdges[group[i]].add(group[e]);
			}
		}

		for(int i = 0; i < groupIdx; i++) dp[i] = money[i];
		long max = 0;
		for(int i = groupIdx - 1; i >= 0; i--) {
			for(int ge : sccEdges[i]) {
				dp[ge] = Math.max(dp[ge], dp[i] + money[ge]);
			}
		}

		for(int i = 0; i < groupIdx; i++) if(restaurant[i]) max = Math.max(max, dp[i]);
		print(max);
	}

	static int scc(int idx) {
		int origVal = parent[idx] = sccIdx++;
		stack.push(idx);
		for(int e : edges[idx]) {
			if(parent[e] == 0) parent[idx] = Math.min(parent[idx], scc(e));
			else if(!finish[e]) parent[idx] = Math.min(parent[idx], parent[e]);
		}

		if(origVal == parent[idx]) {
			long totalMoney = 0;
			while(true) {
				int pop = stack.pop();
				finish[pop] = true;
				group[pop] = groupIdx;
				if(pop == idx) break;
			}
			groupIdx++;
		}
		return parent[idx];
	}

	static int toi(String s) { return Integer.parseInt(s); }
	static long tol(String s) { return Long.parseLong(s); }
	static String[] getLine() throws IOException { return br.readLine().split(" "); }
	static int[] getArr() throws IOException { return Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray(); }
	static <T> void print(T s) { System.out.print(s); }
	static <T> void println(T s) { System.out.println(s); }
}
This post is licensed under CC BY 4.0 by the author.