├── README.md
├── week 1
├── connected_components
│ ├── ConnectedComponents.java
│ ├── connected_components.cpp
│ └── connected_components.py
├── graph_decomposition_problems_1.pdf
└── reachability
│ ├── Reachability.java
│ ├── reachability.cpp
│ └── reachability.py
├── week 2
├── acyclicity
│ ├── Acyclicity.java
│ ├── acyclicity.cpp
│ └── acyclicity.py
├── graph_decomposition_problems_2.pdf
├── strongly_connected
│ ├── StronglyConnected.java
│ ├── strongly_connected.cpp
│ └── strongly_connected.py
└── toposort
│ ├── Toposort.java
│ ├── toposort.cpp
│ └── toposort.py
├── week 3
├── bfs
│ ├── BFS.java
│ ├── bfs.cpp
│ └── bfs.py
├── bipartite
│ ├── Bipartite.java
│ ├── bipartite.cpp
│ └── bipartite.py
└── paths_in_graphs_problems_1.pdf
├── week 4
├── dijkstra
│ ├── Dijkstra.java
│ ├── dijkstra.cpp
│ └── dijkstra.py
├── negative_cycle
│ ├── NegativeCycle.java
│ ├── negative_cycle.cpp
│ └── negative_cycle.py
├── paths_in_graphs_problems_2.pdf
└── shortest_paths
│ ├── ShortestPaths.java
│ ├── shortest_paths.cpp
│ └── shortest_paths.py
├── week 5
├── clustering
│ ├── Clustering.java
│ ├── clustering.cpp
│ └── clustering.py
├── connecting_points
│ ├── ConnectingPoints.java
│ ├── connecting_points.cpp
│ └── connecting_points.py
└── spanning_trees_problems.pdf
└── week 6
├── Advanced-Shortest-Paths.pdf
├── dist_with_coords
├── DistWithCoords.java
├── dist_with_coords.cpp
├── dist_with_coords.py3
└── tests
│ ├── 01
│ ├── 01.a
│ ├── 02
│ ├── 02.a
│ ├── 03
│ └── 03.a
└── friend_suggestion
├── FriendSuggestion.java
├── friend_suggestion.cpp
└── friend_suggestion.py3
/README.md:
--------------------------------------------------------------------------------
1 | # Algorithms on Graphs
2 | Assignments in Java, C++, Python for Algorithms on Graphs on Coursera
3 |
4 | Note: I don't have access to submitting my assignments. It's just for my personal learning purpose.
5 |
6 | ## Week 1
7 | [Study Notes](https://gist.github.com/akueisara/612c88a940b7e2b9c0d6a631df28375e)
8 | ### Programming Assignment 1: Decomposition of Graphs
9 | Problem: [Finding an Exit from a Maze](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%201/reachability)
10 | Problem: [Adding Exits to a Maze](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%201/connected_components)
11 |
12 | ## Week 2
13 | [Study Notes](https://gist.github.com/akueisara/120d8d5b4e1a663c606987b00e6c3c15)
14 | ### Programming Assignment 2: Decomposition of Graphs
15 | Problem: [Checking Consistency of CS Curriculum](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%202/acyclicity)
16 | Problem: [Determining an Order of Courses](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%202/toposort)
17 | Advanced Problem: [Checking Whether Any Intersection in a City
18 | is Reachable from Any Other](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%202/strongly_connected)
19 |
20 | ## Week 3
21 | [Study Notes](https://gist.github.com/akueisara/4d274697d5553837a1973a42d31a2224)
22 | ### Programming Assignment 3: Paths in Graphs
23 | Problem: [Computing the Minimum Number of Flight Segments](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%203/bfs)
24 | Problem: [Checking whether a Graph is Bipartite](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%203/bipartite)
25 |
26 | ## Week 4
27 | [Study Notes](https://gist.github.com/akueisara/00e76a5552e41be21b6838cbfcea4b6c)
28 | ### Programming Assignment 4: Paths in Graphs
29 | Problem: [Computing the Minimum Cost of a Flight](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%204/dijkstra)
30 | Problem: [Detecting Anomalies in Currency Exchange Rates](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%204/negative_cycle)
31 | Advanced Problem: [Exchanging Money Optimally](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%204/shortest_paths)
32 |
33 | ## Week 5
34 | [Study Notes](https://gist.github.com/akueisara/42c7b82c43fb2a1ca78303b1624fa7c7)
35 | ### Programming Assignment 5: Minimum Spanning Trees
36 | Problem: [Building Roads to Connect Cities](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%205/connecting_points)
37 | Problem: [Clustering](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%205/clustering)
38 |
39 | ## Week 6
40 | ### Programming Assignment 6: Advanced Shortest Paths
41 | Problem: [Friend Suggestion](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%206/friend_suggestion)
42 | Problem: [Compute Distance Faster Using Coordinates](https://github.com/akueisara/algorithms-on-graphs/tree/master/week%206/dist_with_coords)
--------------------------------------------------------------------------------
/week 1/connected_components/ConnectedComponents.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Scanner;
3 |
4 | public class ConnectedComponents {
5 | private static int numberOfComponents(ArrayList[] adj) {
6 | int result = 0;
7 | //write your code here
8 | int[] visited = new int[adj.length];
9 | for (int i = 0; i < adj.length; i++) {
10 | if (visited[i] == 0) {
11 | explore(adj, i, visited);
12 | result++;
13 | }
14 | }
15 | return result;
16 | }
17 |
18 | private static void explore(ArrayList[] adj, int x, int[] visited) {
19 | visited[x] = 1;
20 | for (int i = 0; i < adj[x].size(); i++) {
21 | if (visited[adj[x].get(i)] == 0)
22 | explore(adj, adj[x].get(i), visited);
23 | }
24 | }
25 |
26 | public static void main(String[] args) {
27 | Scanner scanner = new Scanner(System.in);
28 | int n = scanner.nextInt();
29 | int m = scanner.nextInt();
30 | ArrayList[] adj = (ArrayList[])new ArrayList[n];
31 | for (int i = 0; i < n; i++) {
32 | adj[i] = new ArrayList();
33 | }
34 | for (int i = 0; i < m; i++) {
35 | int x, y;
36 | x = scanner.nextInt();
37 | y = scanner.nextInt();
38 | adj[x - 1].add(y - 1);
39 | adj[y - 1].add(x - 1);
40 | }
41 | System.out.println(numberOfComponents(adj));
42 | }
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/week 1/connected_components/connected_components.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using std::vector;
5 | using std::pair;
6 |
7 | void explore(vector > &adj, int x, vector &visited) {
8 | visited[x] = 1;
9 | for (int i = 0; i < adj[x].size(); i++) {
10 | if (!visited[adj[x][i]])
11 | explore(adj, adj[x][i], visited);
12 | }
13 | }
14 |
15 | int number_of_components(vector > &adj) {
16 | int res = 0;
17 | //write your code here
18 | vector visited(adj.size());
19 | for (int i = 0; i < adj.size(); i++)
20 | {
21 | if (!visited[i])
22 | {
23 | explore(adj, i, visited);
24 | res++;
25 | }
26 | }
27 | return res;
28 | }
29 |
30 | int main() {
31 | size_t n, m;
32 | std::cin >> n >> m;
33 | vector > adj(n, vector());
34 | for (size_t i = 0; i < m; i++) {
35 | int x, y;
36 | std::cin >> x >> y;
37 | adj[x - 1].push_back(y - 1);
38 | adj[y - 1].push_back(x - 1);
39 | }
40 | std::cout << number_of_components(adj);
41 | }
42 |
--------------------------------------------------------------------------------
/week 1/connected_components/connected_components.py:
--------------------------------------------------------------------------------
1 | def number_of_components(adj):
2 | result = 0
3 | #write your code here
4 | visited = [0] * len(adj)
5 | for i in xrange(len(adj)):
6 | if not visited[i]:
7 | explore(adj, i, visited)
8 | result += 1
9 | return result
10 |
11 | def explore(adj, x, visited):
12 | visited[x] = 1
13 | for i in xrange(len(adj[x])):
14 | if not visited[adj[x][i]]:
15 | explore(adj, adj[x][i], visited)
16 |
17 | if __name__ == '__main__':
18 | n, m = map(int, raw_input().split())
19 | adj = [[] for _ in range(n)]
20 | for i in range(m):
21 | a, b = map(int, raw_input().split())
22 | # adjacency list
23 | adj[a - 1].append(b - 1)
24 | adj[b - 1].append(a - 1)
25 | print(number_of_components(adj))
26 |
--------------------------------------------------------------------------------
/week 1/graph_decomposition_problems_1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akueisara/algo-on-graphs/06c71e9558838a982b624606cd0b5e7def0fd99e/week 1/graph_decomposition_problems_1.pdf
--------------------------------------------------------------------------------
/week 1/reachability/Reachability.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Scanner;
3 |
4 | public class Reachability {
5 | private static int reach(ArrayList[] adj, int x, int y) {
6 | //write your code here
7 | int[] visited = new int[adj.length];
8 | return explore(adj, x, y, visited);
9 | }
10 |
11 | private static int explore(ArrayList[] adj, int x, int y, int[] visited) {
12 | if (x == y) {
13 | return 1;
14 | }
15 | visited[x] = 1;
16 | for (int i = 0; i < adj[x].size(); i++) {
17 | if (visited[adj[x].get(i)] == 0) {
18 | if(explore(adj, adj[x].get(i), y, visited) == 1) {
19 | return 1;
20 | }
21 | }
22 | }
23 | return 0;
24 | }
25 |
26 | public static void main(String[] args) {
27 | Scanner scanner = new Scanner(System.in);
28 | int n = scanner.nextInt();
29 | int m = scanner.nextInt();
30 | ArrayList[] adj = (ArrayList[])new ArrayList[n];
31 | for (int i = 0; i < n; i++) {
32 | adj[i] = new ArrayList();
33 | }
34 | for (int i = 0; i < m; i++) {
35 | int x, y;
36 | x = scanner.nextInt();
37 | y = scanner.nextInt();
38 | // adjacency list
39 | adj[x - 1].add(y - 1);
40 | adj[y - 1].add(x - 1);
41 | }
42 | int x = scanner.nextInt() - 1;
43 | int y = scanner.nextInt() - 1;
44 | System.out.println(reach(adj, x, y));
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/week 1/reachability/reachability.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using std::vector;
5 | using std::pair;
6 |
7 | int explore(vector > &adj, int x, int y, vector &visited) {
8 | if (x == y) {
9 | return 1;
10 | }
11 | visited[x] = 1;
12 | for(int i = 0; i < adj[x].size(); i++) {
13 | if (!visited[adj[x][i]]) {
14 | if(explore(adj, adj[x][i], y, visited)) {
15 | return 1;
16 | }
17 | }
18 | }
19 | return 0;
20 | }
21 |
22 |
23 | int reach(vector > &adj, int x, int y) {
24 | //write your code here
25 | vector visited(adj.size());
26 | return explore(adj, x, y, visited);
27 | }
28 |
29 | int main() {
30 | size_t n, m;
31 | std::cin >> n >> m;
32 | vector > adj(n, vector());
33 | for (size_t i = 0; i < m; i++) {
34 | int x, y;
35 | std::cin >> x >> y;
36 | // adjacency list
37 | adj[x - 1].push_back(y - 1);
38 | adj[y - 1].push_back(x - 1);
39 | }
40 | int x, y;
41 | std::cin >> x >> y;
42 | std::cout << reach(adj, x - 1, y - 1);
43 | }
44 |
--------------------------------------------------------------------------------
/week 1/reachability/reachability.py:
--------------------------------------------------------------------------------
1 | def reach(adj, x, y):
2 | #write your code here
3 | visited = [0] * len(adj)
4 | return explore(adj, x, y, visited)
5 |
6 | def explore(adj, x, y, visited):
7 | if (x == y):
8 | return 1
9 | visited[x] = 1
10 | for i in xrange(len(adj[x])):
11 | if (not visited[adj[x][i]]):
12 | if(explore(adj, adj[x][i], y, visited)):
13 | return 1
14 | return 0
15 |
16 | if __name__ == '__main__':
17 | n, m = map(int, raw_input().split())
18 | adj = [[] for _ in range(n)]
19 | for i in range(m):
20 | a, b = map(int, raw_input().split())
21 | # adjacency list
22 | adj[a - 1].append(b - 1)
23 | adj[b - 1].append(a - 1)
24 | x, y = map(int, raw_input().split())
25 | print(reach(adj, x-1, y-1))
--------------------------------------------------------------------------------
/week 2/acyclicity/Acyclicity.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Scanner;
3 |
4 | public class Acyclicity {
5 | private static int acyclic(ArrayList[] adj) {
6 | // Mark all the vertices as not visited and not part of recursion stack
7 | int[] visited = new int[adj.length];
8 | int[] recStack = new int[adj.length];
9 | // Call the recursive helper function to detect cycle in different DFS trees
10 | for (int i = 0; i < adj.length; i++) {
11 | if (visited[i] == 0) {
12 | if (dfs(adj, i, visited, recStack) == 1)
13 | return 1;
14 | }
15 | }
16 | return 0;
17 | }
18 |
19 | private static int dfs(ArrayList[] adj, int x, int[] visited, int[] recStack) {
20 | // Mark the current node as visited and part of recursion stack
21 | visited[x] = 1;
22 | recStack[x] = 1;
23 | // Recur for all the vertices adjacent to this vertex
24 | for (int i = 0; i < adj[x].size(); i++) {
25 | if (visited[adj[x].get(i)] == 0 && dfs(adj, adj[x].get(i), visited, recStack) == 1)
26 | return 1;
27 | else if(recStack[adj[x].get(i)] == 1)
28 | return 1;
29 | }
30 | recStack[x] = 0; // remove the vertex from recursion stack
31 | return 0;
32 | }
33 |
34 | public static void main(String[] args) {
35 | Scanner scanner = new Scanner(System.in);
36 | int n = scanner.nextInt();
37 | int m = scanner.nextInt();
38 | ArrayList[] adj = (ArrayList[])new ArrayList[n];
39 | for (int i = 0; i < n; i++) {
40 | adj[i] = new ArrayList();
41 | }
42 | for (int i = 0; i < m; i++) {
43 | int x, y;
44 | x = scanner.nextInt();
45 | y = scanner.nextInt();
46 | adj[x - 1].add(y - 1);
47 | }
48 | System.out.println(acyclic(adj));
49 | }
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/week 2/acyclicity/acyclicity.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | using std::vector;
5 | using std::pair;
6 |
7 | int dfs(vector > &adj, int x, vector &visited, vector &recStack) {
8 | // Mark the current node as visited and part of recursion stack
9 | visited[x] = 1;
10 | recStack[x] = 1;
11 | // Recur for all the vertices adjacent to this vertex
12 | for (int i = 0; i < adj[x].size(); i++) {
13 | if (!visited[adj[x][i]] && dfs(adj, adj[x][i], visited, recStack))
14 | return 1;
15 | else if(recStack[adj[x][i]])
16 | return 1;
17 | }
18 | recStack[x] = 0; // remove the vertex from recursion stack
19 | return 0;
20 | }
21 |
22 | int acyclic(vector > &adj) {
23 | // Mark all the vertices as not visited and not part of recursion stack
24 | vector visited(adj.size());
25 | vector recStack(adj.size());
26 | for (int i = 0; i < adj.size(); i++)
27 | {
28 | if (!visited[i]) {
29 | if (dfs(adj, i, visited, recStack))
30 | return 1;
31 | }
32 | }
33 | return 0;
34 | }
35 |
36 | int main() {
37 | size_t n, m;
38 | std::cin >> n >> m;
39 | vector > adj(n, vector());
40 | for (size_t i = 0; i < m; i++) {
41 | int x, y;
42 | std::cin >> x >> y;
43 | adj[x - 1].push_back(y - 1);
44 | }
45 | std::cout << acyclic(adj);
46 | }
47 |
--------------------------------------------------------------------------------
/week 2/acyclicity/acyclicity.py:
--------------------------------------------------------------------------------
1 | def acyclic(adj):
2 | # Mark all the vertices as not visited and not part of recursion stack
3 | visited = [0 for _ in range(len(adj))]
4 | rec_stack = [0 for _ in range(len(adj))]
5 | # Call the recursive helper function to detect cycle in different DFS trees
6 | for i in range(len(adj)):
7 | if not visited[i]:
8 | if dfs(adj, i, visited, rec_stack):
9 | return 1
10 | return 0
11 |
12 | def dfs(adj, x, visited, rec_stack):
13 | # Mark the current node as visited and part of recursion stack
14 | visited[x] = 1
15 | rec_stack[x] = 1
16 | # Recur for all the vertices adjacent to this vertex
17 | for i in range(len(adj[x])):
18 | if not visited[adj[x][i]] and dfs(adj, adj[x][i], visited, rec_stack):
19 | return 1
20 | elif rec_stack[adj[x][i]]:
21 | return 1
22 | rec_stack[x] = 0 # remove the vertex from recursion stack
23 | return 0
24 |
25 | if __name__ == '__main__':
26 | n, m = map(int, raw_input().split())
27 | adj = [[] for _ in range(n)]
28 | for i in range(m):
29 | a, b = map(int, raw_input().split())
30 | # adjacency list
31 | adj[a - 1].append(b - 1)
32 | print(acyclic(adj))
33 |
--------------------------------------------------------------------------------
/week 2/graph_decomposition_problems_2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akueisara/algo-on-graphs/06c71e9558838a982b624606cd0b5e7def0fd99e/week 2/graph_decomposition_problems_2.pdf
--------------------------------------------------------------------------------
/week 2/strongly_connected/StronglyConnected.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Collections;
3 | import java.util.Scanner;
4 | import java.util.Stack;
5 |
6 | public class StronglyConnected {
7 | private static int numberOfStronglyConnectedComponents(ArrayList[] adj) {
8 | int result = 0;
9 | Stack stack = new Stack<>();
10 |
11 | // Mark all the vertices as not visited (For first DFS)
12 | int visited[] = new int[adj.length];
13 |
14 | // Fill vertices in stack according to their finishing times
15 | for(int i = 0; i < adj.length; i++){
16 | if(visited[i] == 0){
17 | dfs(adj, i, visited, stack);
18 | }
19 | }
20 |
21 | // get the reversed adj list
22 | ArrayList[] rAdj = reverseEdges(adj);
23 |
24 | // Mark all the vertices as not visited (For second DFS)
25 | visited = new int[adj.length];
26 |
27 | // Now process all vertices in order defined by Stack
28 | while (! stack.isEmpty()) {
29 | // Pop a vertex from stack
30 | int x = stack.pop();
31 |
32 | // get one Strongly connected component of the popped vertex
33 | if(visited[x] == 0){
34 | dfs(rAdj, x, visited, new Stack());
35 | result++;
36 | }
37 | }
38 | return result;
39 | }
40 |
41 | private static void dfs(ArrayList[] adj, int x, int visited[], Stack stack){
42 | // Mark the current node as visited
43 | visited[x] = 1;
44 |
45 | // Recur for all the vertices adjacent to this vertex
46 | for(int i = 0; i < adj[x].size(); i++){
47 | if(visited[adj[x].get(i)] == 0){
48 | visited[adj[x].get(i)] = 1;
49 | dfs(adj, adj[x].get(i), visited, stack);
50 | }
51 | }
52 |
53 | // All vertices reachable from x are processed by now, push x to Stack
54 | stack.push(x);
55 | }
56 |
57 | private static ArrayList[] reverseEdges(ArrayList[] adj){
58 | ArrayList[] rAdj = new ArrayList[adj.length];
59 | for(int i = 0; i < adj.length; i++){
60 | rAdj[i] = new ArrayList();
61 | }
62 | for(int i = 0; i < adj.length; i++){
63 | // Recur for all the vertices adjacent to this vertex
64 | for(int j = 0; j < adj[i].size(); j++){
65 | rAdj[adj[i].get(j)].add(i);
66 | }
67 | }
68 | return rAdj;
69 | }
70 |
71 | public static void main(String[] args) {
72 | Scanner scanner = new Scanner(System.in);
73 | int n = scanner.nextInt();
74 | int m = scanner.nextInt();
75 | ArrayList[] adj = (ArrayList[])new ArrayList[n];
76 | for (int i = 0; i < n; i++) {
77 | adj[i] = new ArrayList();
78 | }
79 | for (int i = 0; i < m; i++) {
80 | int x, y;
81 | x = scanner.nextInt();
82 | y = scanner.nextInt();
83 | adj[x - 1].add(y - 1);
84 | }
85 | System.out.println(numberOfStronglyConnectedComponents(adj));
86 | }
87 | }
88 |
89 |
--------------------------------------------------------------------------------
/week 2/strongly_connected/strongly_connected.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | using std::vector;
7 | using std::pair;
8 | using std::stack;
9 |
10 | vector > reverseEdges(vector > &adj){
11 | vector > rAdj(adj.size(), vector());
12 | for(int i = 0; i < adj.size(); i++){
13 | // Recur for all the vertices adjacent to this vertex
14 | for(int j = 0; j < adj[i].size(); j++){
15 | rAdj[adj[i][j]].push_back(i);
16 | }
17 | }
18 | return rAdj;
19 | }
20 |
21 | void dfs(vector > &adj, int x, vector &visited, stack &Stack) {
22 | // Mark the current node as visited
23 | visited[x] = 1;
24 |
25 | // Recur for all the vertices adjacent to this vertex
26 | for (int i = 0; i < adj[x].size(); i++) {
27 | if(!visited[adj[x][i]]){
28 | visited[adj[x][i]] = 1;
29 | dfs(adj, adj[x][i], visited, Stack);
30 | }
31 | }
32 |
33 | // All vertices reachable from x are processed by now, push x to Stack
34 | Stack.push(x);
35 | }
36 |
37 | int number_of_strongly_connected_components(vector > adj) {
38 | int result = 0;
39 | stack Stack;
40 |
41 | // Mark all the vertices as not visited (For first DFS)
42 | vector visited(adj.size(), 0);
43 |
44 | // Fill vertices in stack according to their finishing times
45 | for (int i = 0; i < adj.size(); i++) {
46 | if(!visited[i]){
47 | dfs(adj, i, visited, Stack);
48 | }
49 | }
50 |
51 | // get the reversed adj list
52 | vector > rAdj = reverseEdges(adj);
53 |
54 | // Mark all the vertices as not visited (For second DFS)
55 | for(int i = 0; i < adj.size(); i++) {
56 | visited[i] = 0;
57 | }
58 |
59 | // Now process all vertices in order defined by Stack
60 | while (! Stack.empty()) {
61 | // Pop a vertex from stack
62 | int x = Stack.top();
63 | Stack.pop();
64 |
65 | // get one Strongly connected component of the popped vertex
66 | if (!visited[x]) {
67 | stack componentStack;
68 | dfs(rAdj, x, visited, componentStack);
69 | result++;
70 | }
71 | }
72 | return result;
73 | }
74 |
75 | int main() {
76 | size_t n, m;
77 | std::cin >> n >> m;
78 | vector > adj(n, vector());
79 | for (size_t i = 0; i < m; i++) {
80 | int x, y;
81 | std::cin >> x >> y;
82 | adj[x - 1].push_back(y - 1);
83 | }
84 | std::cout << number_of_strongly_connected_components(adj);
85 | }
86 |
--------------------------------------------------------------------------------
/week 2/strongly_connected/strongly_connected.py:
--------------------------------------------------------------------------------
1 | def dfs(adj, x, visited, stack):
2 | # Mark the current node as visited
3 | visited[x] = 1
4 |
5 | # Recur for all the vertices adjacent to this vertex
6 | for i in range(len(adj[x])):
7 | if not visited[adj[x][i]]:
8 | visited[adj[x][i]] = 1
9 | dfs(adj, adj[x][i], visited, stack)
10 |
11 | # All vertices reachable from x are processed by now, push x to Stack
12 | stack.append(x)
13 |
14 | def reverseEdges(adj):
15 | r_adj = [[] for _ in range(len(adj))]
16 | for i in range(len(adj)):
17 | for j in range(len(adj[i])):
18 | r_adj[adj[i][j]].append(i)
19 | return r_adj
20 |
21 | def number_of_strongly_connected_components(adj):
22 | result = 0
23 | stack = []
24 |
25 | # Mark all the vertices as not visited (For first DFS)
26 | visited = [0] * len(adj)
27 |
28 | # Fill vertices in stack according to their finishing times
29 | for i in range(len(adj)):
30 | if not visited[i]:
31 | dfs(adj, i, visited, stack)
32 |
33 | # get the reversed adj list
34 | r_adj = reverseEdges(adj)
35 |
36 | # Mark all the vertices as not visited (For second DFS)
37 | visited = [0] * len(adj)
38 |
39 | # Now process all vertices in order defined by Stack
40 | while stack:
41 | x = stack.pop()
42 | if not visited[x]:
43 | dfs(r_adj, x, visited, [])
44 | result+=1
45 | return result
46 |
47 | if __name__ == '__main__':
48 | n, m = map(int, raw_input().split())
49 | adj = [[] for _ in range(n)]
50 | for i in range(m):
51 | a, b = map(int, raw_input().split())
52 | # adjacency list
53 | adj[a - 1].append(b - 1)
54 | print(number_of_strongly_connected_components(adj))
55 |
--------------------------------------------------------------------------------
/week 2/toposort/Toposort.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Collections;
3 | import java.util.Scanner;
4 |
5 | public class Toposort {
6 | private static ArrayList toposort(ArrayList[] adj) {
7 | int used[] = new int[adj.length];
8 | ArrayList order = new ArrayList();
9 | for (int i = 0; i < adj.length; i++) {
10 | if (used[i] == 0) {
11 | dfs(adj, used, order, i);
12 | }
13 | }
14 | return order;
15 | }
16 |
17 | private static void dfs(ArrayList[] adj, int[] used, ArrayList order, int s) {
18 | used[s] = 1;
19 | for (int i = 0; i < adj[s].size(); i++) {
20 | if (used[adj[s].get(i)] == 0) {
21 | dfs(adj, used, order, adj[s].get(i));
22 | }
23 | }
24 | order.add(0, s);
25 | }
26 |
27 | public static void main(String[] args) {
28 | Scanner scanner = new Scanner(System.in);
29 | int n = scanner.nextInt();
30 | int m = scanner.nextInt();
31 | ArrayList[] adj = (ArrayList[])new ArrayList[n];
32 | for (int i = 0; i < n; i++) {
33 | adj[i] = new ArrayList();
34 | }
35 | for (int i = 0; i < m; i++) {
36 | int x, y;
37 | x = scanner.nextInt();
38 | y = scanner.nextInt();
39 | adj[x - 1].add(y - 1);
40 | }
41 | ArrayList order = toposort(adj);
42 | for (int x : order) {
43 | System.out.print((x + 1) + " ");
44 | }
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/week 2/toposort/toposort.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | using std::vector;
6 | using std::pair;
7 |
8 | void dfs(vector > &adj, vector &used, vector &order, int x) {
9 | used[x] = 1;
10 | for (int i = 0; i < adj[x].size(); i++) {
11 | if(!used[adj[x][i]])
12 | dfs(adj, used, order, adj[x][i]);
13 | }
14 | order.insert(order.begin(), x);
15 | }
16 |
17 | vector toposort(vector > adj) {
18 | vector used(adj.size(), 0);
19 | vector order;
20 | for (int i = 0; i < adj.size(); i++) {
21 | if (!used[i]) {
22 | dfs(adj, used, order, i);
23 | }
24 | }
25 | return order;
26 | }
27 |
28 | int main() {
29 | size_t n, m;
30 | std::cin >> n >> m;
31 | vector > adj(n, vector());
32 | for (size_t i = 0; i < m; i++) {
33 | int x, y;
34 | std::cin >> x >> y;
35 | adj[x - 1].push_back(y - 1);
36 | }
37 | vector order = toposort(adj);
38 | for (size_t i = 0; i < order.size(); i++) {
39 | std::cout << order[i] + 1 << " ";
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/week 2/toposort/toposort.py:
--------------------------------------------------------------------------------
1 | #Uses python3
2 |
3 | import sys
4 |
5 | def dfs(adj, used, order, x):
6 | used[x] = 1
7 | for i in range(len(adj[x])):
8 | if not used[adj[x][i]]:
9 | dfs(adj, used, order, adj[x][i])
10 | order.append(x)
11 |
12 |
13 | def toposort(adj):
14 | used = [0] * len(adj)
15 | order = []
16 | for i in range(len(adj)):
17 | if not used[i]:
18 | dfs(adj, used, order, i)
19 | order.reverse()
20 | return order
21 |
22 | if __name__ == '__main__':
23 | n, m = map(int, raw_input().split())
24 | adj = [[] for _ in range(n)]
25 | for i in range(m):
26 | a, b = map(int, raw_input().split())
27 | # adjacency list
28 | adj[a - 1].append(b - 1)
29 | order = toposort(adj)
30 | for x in order:
31 | print x + 1,
32 |
33 |
--------------------------------------------------------------------------------
/week 3/bfs/BFS.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.LinkedList;
3 | import java.util.Queue;
4 | import java.util.Scanner;
5 |
6 | public class BFS {
7 | private static int distance(ArrayList[] adj, int s, int t) {
8 | //write your code here
9 | if (s == t) {
10 | return 0;
11 | }
12 |
13 | int[] dist = new int[adj.length];
14 | for(int i=0; i queue = new LinkedList();
22 |
23 | // Enqueue the current node
24 | queue.add(s);
25 |
26 | while (!queue.isEmpty()) {
27 | // Dequeue a vertex from queue
28 | int u = queue.poll();
29 |
30 | // Get all adjacent vertices of the dequeued vertex u
31 | // If a adjacent has not been discovered, then enqueue it
32 | for (int v: adj[u]) {
33 | if (dist[v] == Integer.MAX_VALUE) {
34 | queue.add(v);
35 | dist[v] = dist[u] + 1;
36 | }
37 | }
38 | }
39 |
40 | if(dist[t] != Integer.MAX_VALUE) {
41 | return dist[t];
42 | }
43 |
44 | return -1;
45 | }
46 |
47 | public static void main(String[] args) {
48 | Scanner scanner = new Scanner(System.in);
49 | int n = scanner.nextInt();
50 | int m = scanner.nextInt();
51 | ArrayList[] adj = (ArrayList[])new ArrayList[n];
52 | for (int i = 0; i < n; i++) {
53 | adj[i] = new ArrayList();
54 | }
55 | for (int i = 0; i < m; i++) {
56 | int x, y;
57 | x = scanner.nextInt();
58 | y = scanner.nextInt();
59 | adj[x - 1].add(y - 1);
60 | adj[y - 1].add(x - 1);
61 | }
62 | int x = scanner.nextInt() - 1;
63 | int y = scanner.nextInt() - 1;
64 | System.out.println(distance(adj, x, y));
65 | }
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/week 3/bfs/bfs.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | using std::vector;
8 | using std::queue;
9 | using std::numeric_limits;
10 | using std::queue;
11 |
12 | int distance(vector > &adj, int s, int t) {
13 | //write your code here
14 | if (s == t) {
15 | return 0;
16 | }
17 |
18 | vector dist(adj.size());
19 | for(int i=0; i::max();
21 | }
22 |
23 | dist[s] = 0;
24 |
25 | // Create a queue for BFS
26 | queue queue;
27 |
28 | // Enqueue the current node
29 | queue.push(s);
30 |
31 | while(!queue.empty()) {
32 | // Dequeue a vertex from queue
33 | int u = queue.front();
34 | queue.pop();
35 |
36 | // Get all adjacent vertices of the dequeued vertex u
37 | // If a adjacent has not been discovered, then enqueue it
38 | for(int i=0; i < adj[u].size(); ++i) {
39 | int v = adj[u][i];
40 | if(dist[v] == numeric_limits::max()) {
41 | queue.push(v);
42 | dist[v] = dist[u] + 1;
43 | }
44 | }
45 | }
46 |
47 | if(dist[t] != numeric_limits::max()) {
48 | return dist[t];
49 | }
50 |
51 | return -1;
52 | }
53 |
54 | int main() {
55 | int n, m;
56 | std::cin >> n >> m;
57 | vector > adj(n, vector());
58 | for (int i = 0; i < m; i++) {
59 | int x, y;
60 | std::cin >> x >> y;
61 | adj[x - 1].push_back(y - 1);
62 | adj[y - 1].push_back(x - 1);
63 | }
64 | int s, t;
65 | std::cin >> s >> t;
66 | s--, t--;
67 | std::cout << distance(adj, s, t);
68 | }
69 |
--------------------------------------------------------------------------------
/week 3/bfs/bfs.py:
--------------------------------------------------------------------------------
1 | def distance(adj, s, t):
2 | #write your code here
3 | dist = [len(adj)] * len(adj)
4 | dist[s] = 0
5 | queue = []
6 | queue.append(s)
7 | while queue:
8 | u = queue.pop(0)
9 | for v in adj[u]:
10 | if dist[v] == len(adj):
11 | queue.append(v)
12 | dist[v] = dist[u] + 1
13 | if dist[t] != len(adj):
14 | return dist[t]
15 | return -1
16 |
17 | if __name__ == '__main__':
18 | n, m = map(int, raw_input().split())
19 | adj = [[] for _ in range(n)]
20 | for i in range(m):
21 | a, b = map(int, raw_input().split())
22 | # adjacency list
23 | adj[a - 1].append(b - 1)
24 | adj[b - 1].append(a - 1)
25 | s, t = map(int, raw_input().split())
26 | s = s - 1
27 | t = t - 1
28 | print(distance(adj, s, t))
29 |
--------------------------------------------------------------------------------
/week 3/bipartite/Bipartite.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.LinkedList;
3 | import java.util.Queue;
4 | import java.util.Scanner;
5 |
6 | public class Bipartite {
7 | // This function returns 1 if the graph is Bipartite, else 0
8 | private static int bipartite(ArrayList[] adj) {
9 | //write your code here
10 | // Create a color array to store colors assigned to all veritces.
11 | // Vertex number is used as index in this array. The value '-1'
12 | // of colorArr[i] is used to indicate that no color is assigned
13 | // to vertex 'i'. The value 1 is used to indicate first color
14 | // is assigned and value 0 indicates second color is assigned.
15 | int[] colorArr = new int[adj.length];
16 | for(int i=0; i queue = new LinkedList();
26 | queue.add(0);
27 |
28 | // Run while there are vertices in queue (Similar to BFS)
29 | while (!queue.isEmpty()) {
30 | // Dequeue a vertex from queue
31 | int u = queue.poll();
32 |
33 | // Find all non-colored adjacent vertices
34 | for (int v: adj[u]) {
35 | // Destination v is not colored
36 | if (colorArr[v] == -1) {
37 | // Assign alternate color to this adjacent v of u
38 | colorArr[v] = 1- colorArr[u];
39 | queue.add(v);
40 | }
41 |
42 | // Destination v is colored with same color as u
43 | else if (colorArr[v] == colorArr[u])
44 | return 0;
45 | }
46 | }
47 | // If we reach here, then all adjacent vertices can
48 | // be colored with alternate color
49 | return 1;
50 | }
51 |
52 | public static void main(String[] args) {
53 | Scanner scanner = new Scanner(System.in);
54 | int n = scanner.nextInt();
55 | int m = scanner.nextInt();
56 | ArrayList[] adj = (ArrayList[])new ArrayList[n];
57 | for (int i = 0; i < n; i++) {
58 | adj[i] = new ArrayList();
59 | }
60 | for (int i = 0; i < m; i++) {
61 | int x, y;
62 | x = scanner.nextInt();
63 | y = scanner.nextInt();
64 | adj[x - 1].add(y - 1);
65 | adj[y - 1].add(x - 1);
66 | }
67 | System.out.println(bipartite(adj));
68 | }
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/week 3/bipartite/bipartite.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | using std::vector;
6 | using std::queue;
7 |
8 | int bipartite(vector > &adj) {
9 | //write your code here
10 | // Create a color array to store colors assigned to all veritces.
11 | // Vertex number is used as index in this array. The value '-1'
12 | // of colorArr[i] is used to indicate that no color is assigned
13 | // to vertex 'i'. The value 1 is used to indicate first color
14 | // is assigned and value 0 indicates second color is assigned.
15 | int colorArr[adj.size()];
16 | for (int i = 0; i < adj.size(); ++i)
17 | colorArr[i] = -1;
18 |
19 | // Assign first color to the source vertex
20 | colorArr[0] = 1;
21 |
22 | // Create a queue (FIFO) of vertex numbers and enqueue
23 | // source vertex for BFS traversal
24 | queue queue;
25 | queue.push(0);
26 |
27 | // Run while there are vertices in queue (Similar to BFS)
28 | while(!queue.empty()) {
29 | // Dequeue a vertex from queue
30 | int u = queue.front();
31 | queue.pop();
32 |
33 | // Find all non-colored adjacent vertices
34 | for(int i=0; i < adj[u].size(); ++i) {
35 | int v = adj[u][i];
36 | // Destination v is not colored
37 | if (colorArr[v] == -1) {
38 | // Assign alternate color to this adjacent v of u
39 | colorArr[v] = 1- colorArr[u];
40 | queue.push(v);
41 | }
42 |
43 | // Destination v is colored with same color as u
44 | else if (colorArr[v] == colorArr[u])
45 | return 0;
46 | }
47 | }
48 | // If we reach here, then all adjacent vertices can
49 | // be colored with alternate color
50 | return 1;
51 | }
52 |
53 | int main() {
54 | int n, m;
55 | std::cin >> n >> m;
56 | vector > adj(n, vector());
57 | for (int i = 0; i < m; i++) {
58 | int x, y;
59 | std::cin >> x >> y;
60 | adj[x - 1].push_back(y - 1);
61 | adj[y - 1].push_back(x - 1);
62 | }
63 | std::cout << bipartite(adj);
64 | }
65 |
--------------------------------------------------------------------------------
/week 3/bipartite/bipartite.py:
--------------------------------------------------------------------------------
1 | def bipartite(adj):
2 | #write your code here
3 | color_arr = [-1] * len(adj)
4 | color_arr[0] = 1
5 | queue = []
6 | queue.append(0)
7 | while queue:
8 | u = queue.pop(0)
9 | for v in adj[u]:
10 | if color_arr[v] == -1:
11 | color_arr[v] = 1 - color_arr[u]
12 | queue.append(v)
13 | elif color_arr[v] == color_arr[u]:
14 | return 0
15 | return 1
16 |
17 | if __name__ == '__main__':
18 | n, m = map(int, raw_input().split())
19 | adj = [[] for _ in range(n)]
20 | for i in range(m):
21 | a, b = map(int, raw_input().split())
22 | # adjacency list
23 | adj[a - 1].append(b - 1)
24 | adj[b - 1].append(a - 1)
25 | print(bipartite(adj))
26 |
--------------------------------------------------------------------------------
/week 3/paths_in_graphs_problems_1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akueisara/algo-on-graphs/06c71e9558838a982b624606cd0b5e7def0fd99e/week 3/paths_in_graphs_problems_1.pdf
--------------------------------------------------------------------------------
/week 4/dijkstra/Dijkstra.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 | public class Dijkstra {
4 |
5 | private static final int inf = Integer.MAX_VALUE;
6 |
7 | public static class Node implements Comparable {
8 | int index;
9 | long distance;
10 |
11 | public Node(int index, long distance) {
12 | this.index = index;
13 | this.distance = distance;
14 | }
15 |
16 | @Override
17 | public int compareTo(Node o) {
18 | if (this.distance > o.distance) return 1;
19 | else if (this.distance < o.distance) return -1;
20 | else return 0;
21 | }
22 | }
23 |
24 | private static int distance(ArrayList[] adj, ArrayList[] cost, int s, int t) {
25 | //write your code here
26 | int[] dist = new int[adj.length];
27 | for (int i = 0;i < dist.length;i++) {
28 | dist[i] = inf;
29 | }
30 | dist[s] = 0;
31 | PriorityQueue queue = new PriorityQueue();
32 | queue.add(new Node(s, dist[s]));
33 | while(!queue.isEmpty()){
34 | Node u = queue.remove();
35 | int u_index = u.index;
36 | for (int v : adj[u_index]) {
37 | int v_index = adj[u_index].indexOf(v);
38 | if (dist[v] > dist[u_index] + cost[u_index].get(v_index)) {
39 | dist[v] = dist[u_index] + cost[u_index].get(v_index);
40 | queue.add(new Node(v, dist[v]));
41 | }
42 | }
43 | }
44 | if(dist[t] == inf)
45 | return -1;
46 | return dist[t];
47 | }
48 |
49 | public static void main(String[] args) {
50 | Scanner scanner = new Scanner(System.in);
51 | int n = scanner.nextInt();
52 | int m = scanner.nextInt();
53 | ArrayList[] adj = (ArrayList[])new ArrayList[n];
54 | ArrayList[] cost = (ArrayList[])new ArrayList[n];
55 | for (int i = 0; i < n; i++) {
56 | adj[i] = new ArrayList();
57 | cost[i] = new ArrayList();
58 | }
59 | for (int i = 0; i < m; i++) {
60 | int x, y, w;
61 | x = scanner.nextInt();
62 | y = scanner.nextInt();
63 | w = scanner.nextInt();
64 | adj[x - 1].add(y - 1);
65 | cost[x - 1].add(w);
66 | }
67 | int x = scanner.nextInt() - 1;
68 | int y = scanner.nextInt() - 1;
69 | System.out.println(distance(adj, cost, x, y));
70 | }
71 | }
72 |
73 |
--------------------------------------------------------------------------------
/week 4/dijkstra/dijkstra.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | using std::vector;
7 | using std::queue;
8 | using std::pair;
9 | using std::priority_queue;
10 | using std::numeric_limits;
11 |
12 | const int inf = numeric_limits::max();
13 |
14 | struct Node {
15 | int index, distance;
16 | Node(int a = 0, int b = 0): index(a), distance(b) {}
17 | };
18 |
19 | struct cmp {
20 | bool operator()(Node a, Node b){
21 | return a.distance > b.distance;
22 | }
23 | };
24 |
25 | int distance(vector > &adj, vector > &cost, int s, int t) {
26 | //write your code here
27 | vector dist(adj.size(), inf);
28 | dist[s] = 0;
29 | priority_queue, cmp> pq;
30 | pq.push(Node(s, dist[s]));
31 | while(!pq.empty()) {
32 | Node u = pq.top();
33 | pq.pop();
34 | int u_index = u.index;
35 | for (int i = 0; i < adj[u_index].size(); i++) {
36 | int v = adj[u_index][i];
37 | if(dist[v] > dist[u_index] + cost[u_index][i]) {
38 | dist[v] = dist[u_index] + cost[u_index][i];
39 | pq.push(Node(v, dist[v]));
40 | }
41 | }
42 | }
43 | if(dist[t] == inf)
44 | return -1;
45 | return dist[t];
46 | }
47 |
48 | int main() {
49 | int n, m;
50 | std::cin >> n >> m;
51 | vector > adj(n, vector());
52 | vector > cost(n, vector());
53 | for (int i = 0; i < m; i++) {
54 | int x, y, w;
55 | std::cin >> x >> y >> w;
56 | adj[x - 1].push_back(y - 1);
57 | cost[x - 1].push_back(w);
58 | }
59 | int s, t;
60 | std::cin >> s >> t;
61 | s--, t--;
62 | std::cout << distance(adj, cost, s, t);
63 | }
64 |
--------------------------------------------------------------------------------
/week 4/dijkstra/dijkstra.py:
--------------------------------------------------------------------------------
1 | #Uses python3
2 | #import sys
3 |
4 | import Queue # change to import queue if using python 3
5 |
6 | class Node(object):
7 | def __init__(self, index, distance):
8 | self.index = index
9 | self.distance = distance
10 | def __cmp__(self, other):
11 | return cmp(self.distance, other.distance)
12 |
13 | def distance(adj, cost, s, t):
14 | #write your code here
15 | dist=[float('inf')]*len(adj)
16 | dist[s] = 0
17 | pq = Queue.PriorityQueue()
18 | pq.put(Node(s, dist[s]))
19 | while not pq.empty():
20 | u = pq.get()
21 | u_index = u.index
22 | for v in adj[u_index]:
23 | v_index = adj[u_index].index(v)
24 | if dist[v] > dist[u_index] + cost[u_index][v_index]:
25 | dist[v] = dist[u_index] + cost[u_index][v_index]
26 | pq.put(Node(v, dist[v]))
27 | if dist[t] == float('inf'):
28 | return -1
29 | return dist[t]
30 |
31 |
32 | if __name__ == '__main__':
33 | n, m = map(int, raw_input().split())
34 | adj = [[] for _ in range(n)]
35 | cost = [[] for _ in range(n)]
36 | for i in range(m):
37 | a, b, w = map(int, raw_input().split())
38 | adj[a - 1].append(b - 1)
39 | cost[a - 1].append(w)
40 | s, t = map(int, raw_input().split())
41 | s, t = s-1, t-1
42 | print(distance(adj, cost, s, t))
43 |
44 | '''
45 | input = sys.stdin.read()
46 | data = list(map(int, input.split()))
47 | n, m = data[0:2]
48 | data = data[2:]
49 | edges = list(zip(zip(data[0:(3 * m):3], data[1:(3 * m):3]), data[2:(3 * m):3]))
50 | data = data[3 * m:]
51 | adj = [[] for _ in range(n)]
52 | cost = [[] for _ in range(n)]
53 | for ((a, b), w) in edges:
54 | adj[a - 1].append(b - 1)
55 | cost[a - 1].append(w)
56 | s, t = data[0] - 1, data[1] - 1
57 | print(distance(adj, cost, s, t))
58 | '''
59 |
--------------------------------------------------------------------------------
/week 4/negative_cycle/NegativeCycle.java:
--------------------------------------------------------------------------------
1 | import java.util.ArrayList;
2 | import java.util.Scanner;
3 |
4 | public class NegativeCycle {
5 | private static final int inf = Integer.MAX_VALUE;
6 |
7 | private static int negativeCycle(ArrayList[] adj, ArrayList[] cost) {
8 | // write your code here
9 | long[] dist = new long[adj.length];
10 | for (int i = 0;i < adj.length; i++) {
11 | dist[i] = inf;
12 | }
13 | dist[0] = 0;
14 | for (int i = 0; i < adj.length; i++) {
15 | for(int u = 0; u < adj.length; u++){
16 | for (int v : adj[u]) {
17 | int v_index = adj[u].indexOf(v);
18 | if (dist[v] > dist[u] + cost[u].get(v_index)) {
19 | dist[v] = dist[u] + cost[u].get(v_index);
20 | if(i == adj.length - 1)
21 | return 1;
22 | }
23 | }
24 | }
25 | }
26 | return 0;
27 | }
28 |
29 | public static void main(String[] args) {
30 | Scanner scanner = new Scanner(System.in);
31 | int n = scanner.nextInt();
32 | int m = scanner.nextInt();
33 | ArrayList[] adj = (ArrayList[])new ArrayList[n];
34 | ArrayList[] cost = (ArrayList[])new ArrayList[n];
35 | for (int i = 0; i < n; i++) {
36 | adj[i] = new ArrayList();
37 | cost[i] = new ArrayList();
38 | }
39 | for (int i = 0; i < m; i++) {
40 | int x, y, w;
41 | x = scanner.nextInt();
42 | y = scanner.nextInt();
43 | w = scanner.nextInt();
44 | adj[x - 1].add(y - 1);
45 | cost[x - 1].add(w);
46 | }
47 | System.out.println(negativeCycle(adj, cost));
48 | }
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/week 4/negative_cycle/negative_cycle.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | using std::vector;
6 | using std::numeric_limits;
7 |
8 | const int inf = numeric_limits::max();
9 |
10 | int negative_cycle(vector > &adj, vector > &cost) {
11 | //write your code here
12 | vector dist(adj.size(), inf);
13 | dist[0] = 0;
14 | for (int i = 0; i < adj.size(); i++) {
15 | for(int u = 0; u < adj.size(); u++){
16 | for (int k = 0; k < adj[u].size(); k++) {
17 | int v = adj[u][k];
18 | if(dist[u] != inf && dist[v] > dist[u] + cost[u][k]) {
19 | dist[v] = dist[u] + cost[u][k];
20 | if(i == adj.size() - 1)
21 | return 1;
22 | }
23 | }
24 | }
25 | }
26 | return 0;
27 | }
28 |
29 | int main() {
30 | int n, m;
31 | std::cin >> n >> m;
32 | vector > adj(n, vector());
33 | vector > cost(n, vector());
34 | for (int i = 0; i < m; i++) {
35 | int x, y, w;
36 | std::cin >> x >> y >> w;
37 | adj[x - 1].push_back(y - 1);
38 | cost[x - 1].push_back(w);
39 | }
40 | std::cout << negative_cycle(adj, cost);
41 | }
42 |
--------------------------------------------------------------------------------
/week 4/negative_cycle/negative_cycle.py:
--------------------------------------------------------------------------------
1 | #Uses python3
2 | #import sys
3 |
4 | def negative_cycle(adj, cost):
5 | #write your code here
6 | dist=[float('inf')]*len(adj)
7 | dist[0] = 0
8 | for i in range(len(adj)):
9 | for u in range(len(adj)):
10 | for v in adj[u]:
11 | v_index = adj[u].index(v)
12 | if dist[v] > dist[u] + cost[u][v_index]:
13 | dist[v] = dist[u] + cost[u][v_index]
14 | if i == len(adj) - 1:
15 | return 1
16 | return 0
17 |
18 |
19 | if __name__ == '__main__':
20 | n, m = map(int, raw_input().split())
21 | adj = [[] for _ in range(n)]
22 | cost = [[] for _ in range(n)]
23 | for i in range(m):
24 | a, b, w = map(int, raw_input().split())
25 | adj[a - 1].append(b - 1)
26 | cost[a - 1].append(w)
27 | print(negative_cycle(adj, cost))
28 | '''
29 | input = sys.stdin.read()
30 | data = list(map(int, input.split()))
31 | n, m = data[0:2]
32 | data = data[2:]
33 | edges = list(zip(zip(data[0:(3 * m):3], data[1:(3 * m):3]), data[2:(3 * m):3]))
34 | data = data[3 * m:]
35 | adj = [[] for _ in range(n)]
36 | cost = [[] for _ in range(n)]
37 | for ((a, b), w) in edges:
38 | adj[a - 1].append(b - 1)
39 | cost[a - 1].append(w)
40 | print(negative_cycle(adj, cost))
41 | '''
42 |
--------------------------------------------------------------------------------
/week 4/paths_in_graphs_problems_2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akueisara/algo-on-graphs/06c71e9558838a982b624606cd0b5e7def0fd99e/week 4/paths_in_graphs_problems_2.pdf
--------------------------------------------------------------------------------
/week 4/shortest_paths/ShortestPaths.java:
--------------------------------------------------------------------------------
1 | import java.util.*;
2 |
3 | public class ShortestPaths {
4 |
5 | private static void shortestPaths(ArrayList < Integer > [] adj, ArrayList < Integer > [] cost, int s, long[] distance, int[] reachable, int[] shortest) {
6 | //write your code here
7 | distance[s] = 0;
8 | reachable[s] = 1;
9 | Queue < Integer > queue = new LinkedList < > ();
10 | for (int i = 0; i < adj.length; i++) {
11 | for (int u = 0; u < adj.length; u++) {
12 | for (int v: adj[u]) {
13 | int v_index = adj[u].indexOf(v);
14 | if (distance[u] != Long.MAX_VALUE && distance[v] > distance[u] + cost[u].get(v_index)) {
15 | distance[v] = distance[u] + cost[u].get(v_index);
16 | reachable[v] = 1;
17 | if (i == adj.length - 1) {
18 | queue.add(v);
19 | }
20 | }
21 | }
22 | }
23 | }
24 |
25 | int[] visited = new int[adj.length];
26 | while (!queue.isEmpty()) {
27 | int u = queue.remove();
28 | visited[u] = 1;
29 | if (u != s)
30 | shortest[u] = 0;
31 | for (int v: adj[u]) {
32 | if (visited[v] == 0) {
33 | queue.add(v);
34 | visited[v] = 1;
35 | shortest[v] = 0;
36 | }
37 | }
38 | }
39 | distance[s] = 0;
40 | }
41 |
42 | public static void main(String[] args) {
43 | Scanner scanner = new Scanner(System.in);
44 | int n = scanner.nextInt();
45 | int m = scanner.nextInt();
46 | ArrayList < Integer > [] adj = (ArrayList < Integer > []) new ArrayList[n];
47 | ArrayList < Integer > [] cost = (ArrayList < Integer > []) new ArrayList[n];
48 | for (int i = 0; i < n; i++) {
49 | adj[i] = new ArrayList < Integer > ();
50 | cost[i] = new ArrayList < Integer > ();
51 | }
52 | for (int i = 0; i < m; i++) {
53 | int x, y, w;
54 | x = scanner.nextInt();
55 | y = scanner.nextInt();
56 | w = scanner.nextInt();
57 | adj[x - 1].add(y - 1);
58 | cost[x - 1].add(w);
59 | }
60 | int s = scanner.nextInt() - 1;
61 | long distance[] = new long[n];
62 | int reachable[] = new int[n];
63 | int shortest[] = new int[n];
64 | for (int i = 0; i < n; i++) {
65 | distance[i] = Long.MAX_VALUE;
66 | reachable[i] = 0;
67 | shortest[i] = 1;
68 | }
69 | shortestPaths(adj, cost, s, distance, reachable, shortest);
70 | for (int i = 0; i < n; i++) {
71 | if (reachable[i] == 0) {
72 | System.out.println('*');
73 | } else if (shortest[i] == 0) {
74 | System.out.println('-');
75 | } else {
76 | System.out.println(distance[i]);
77 | }
78 | }
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/week 4/shortest_paths/shortest_paths.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | using std::vector;
7 | using std::queue;
8 | using std::pair;
9 | using std::priority_queue;
10 |
11 | void shortest_paths(vector > &adj, vector > &cost, int s, vector &distance, vector &reachable, vector &shortest) {
12 | //write your code here
13 | reachable[s] = 1;
14 | distance[s] = 0;
15 | queue q;
16 | for (int i = 0; i < adj.size(); i++) {
17 | for (int u = 0; u < adj.size(); u++){
18 | for (int k = 0; k < adj[u].size(); k++) {
19 | int v = adj[u][k];
20 | if (distance[u]!= std::numeric_limits::max() && distance[v] > distance[u] + cost[u][k]) {
21 | distance[v] = distance[u] + cost[u][k];
22 | reachable[v] = 1;
23 | if (i == adj.size() - 1) {
24 | q.push(v);
25 | }
26 | }
27 | }
28 | }
29 | }
30 |
31 | vector visited(adj.size());
32 | while (!q.empty()){
33 | int u = q.front();
34 | q.pop();
35 | visited[u] = 1;
36 | // if(u != s)
37 | shortest[u] = 0;
38 | for (int i = 0; i < adj[u].size(); i++) {
39 | int v = adj[u][i];
40 | if (!visited[v]) {
41 | q.push(v);
42 | visited[v] = 1;
43 | shortest[v] = 0;
44 | }
45 | }
46 | }
47 | distance[s] = 0;
48 | }
49 |
50 | int main() {
51 | int n, m, s;
52 | std::cin >> n >> m;
53 | vector > adj(n, vector());
54 | vector > cost(n, vector());
55 | for (int i = 0; i < m; i++) {
56 | int x, y, w;
57 | std::cin >> x >> y >> w;
58 | adj[x - 1].push_back(y - 1);
59 | cost[x - 1].push_back(w);
60 | }
61 | std::cin >> s;
62 | s--;
63 | vector distance(n, std::numeric_limits::max());
64 | vector reachable(n, 0);
65 | vector shortest(n, 1);
66 | shortest_paths(adj, cost, s, distance, reachable, shortest);
67 | for (int i = 0; i < n; i++) {
68 | if (!reachable[i]) {
69 | std::cout << "*\n";
70 | } else if (!shortest[i]) {
71 | std::cout << "-\n";
72 | } else {
73 | std::cout << distance[i] << "\n";
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/week 4/shortest_paths/shortest_paths.py:
--------------------------------------------------------------------------------
1 | #Uses python3
2 | #import sys
3 | #import queue
4 |
5 | #Uses python2
6 | import Queue
7 |
8 |
9 | def shortet_paths(adj, cost, s, distance, reachable, shortest):
10 | #write your code here
11 | distance[s] = 0
12 | reachable[s] = 1
13 | q = Queue.Queue()
14 | for i in range(len(adj)):
15 | for u in range(len(adj)):
16 | for v in adj[u]:
17 | v_index = adj[u].index(v)
18 | if distance[u] != 10**19 and distance[v] > distance[u] + cost[u][v_index]:
19 | distance[v] = distance[u] + cost[u][v_index]
20 | reachable[v] = 1
21 | if i == len(adj) - 1:
22 | q.put(v)
23 |
24 | visited = [0] * len(adj)
25 | while not q.empty():
26 | u = q.get()
27 | visited[u] = 1
28 | if u != s:
29 | shortest[u] = 0
30 | for v in adj[u]:
31 | if visited[v] == 0:
32 | q.put(v)
33 | visited[v] = 1
34 | shortest[v] = 0
35 | distance[s] = 0
36 |
37 | if __name__ == '__main__':
38 | n, m = map(int, raw_input().split())
39 | adj = [[] for _ in range(n)]
40 | cost = [[] for _ in range(n)]
41 | for i in range(m):
42 | a, b, w = map(int, raw_input().split())
43 | adj[a - 1].append(b - 1)
44 | cost[a - 1].append(w)
45 | s = int(raw_input())
46 | '''
47 | input = sys.stdin.read()
48 | data = list(map(int, input.split()))
49 | n, m = data[0:2]
50 | data = data[2:]
51 | edges = list(zip(zip(data[0:(3 * m):3], data[1:(3 * m):3]), data[2:(3 * m):3]))
52 | data = data[3 * m:]
53 | adj = [[] for _ in range(n)]
54 | cost = [[] for _ in range(n)]
55 | for ((a, b), w) in edges:
56 | adj[a - 1].append(b - 1)
57 | cost[a - 1].append(w)
58 | s = data[0]
59 | '''
60 | s -= 1
61 | distance = [10**19] * n
62 | reachable = [0] * n
63 | shortest = [1] * n
64 | shortet_paths(adj, cost, s, distance, reachable, shortest)
65 | for x in range(n):
66 | if reachable[x] == 0:
67 | print('*')
68 | elif shortest[x] == 0:
69 | print('-')
70 | else:
71 | print(distance[x])
72 |
--------------------------------------------------------------------------------
/week 5/clustering/Clustering.java:
--------------------------------------------------------------------------------
1 | import java.util.Scanner;
2 | import java.util.PriorityQueue;
3 | import java.util.Comparator;
4 |
5 | public class Clustering {
6 | private static class Node {
7 | int x;
8 | int y;
9 | int parent;
10 | int rank;
11 |
12 | public Node(int a, int b, int c) {
13 | x = a;
14 | y = b;
15 | parent = c;
16 | rank = 0;
17 | }
18 | }
19 |
20 | private static class Edge {
21 | int u;
22 | int v;
23 | double weight;
24 |
25 | public Edge(int a, int b, double c) {
26 | u = a;
27 | v = b;
28 | weight = c;
29 | }
30 | }
31 |
32 | private static void MakeSet(int i, Node[] nodes, int[] x, int[] y) {
33 | nodes[i] = new Node(x[i], y[i], i);
34 | }
35 |
36 | private static double Weight(int x1, int y1, int x2, int y2) {
37 | return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
38 | }
39 |
40 | private static int Find(int i, Node[] nodes) {
41 | if (i != nodes[i].parent) {
42 | nodes[i].parent = Find(nodes[i].parent, nodes);
43 | }
44 | return nodes[i].parent;
45 | }
46 |
47 | private static void Union(int u, int v, Node[] nodes) {
48 | int r1 = Find(u, nodes);
49 | int r2 = Find(v, nodes);
50 | if (r1 != r2) {
51 | if (nodes[r1].rank > nodes[r2].rank) {
52 | nodes[r2].parent = r1;
53 | } else {
54 | nodes[r1].parent = r2;
55 | if (nodes[r1].rank == nodes[r2].rank) {
56 | nodes[r2].rank++;
57 | }
58 | }
59 | }
60 | }
61 |
62 | private static double clustering(int[] x, int[] y, int k) {
63 | //write your code here
64 | int n = x.length;
65 | Node[] nodes = new Node[n];
66 | for (int i = 0; i < n; i++) {
67 | MakeSet(i, nodes, x, y);
68 | }
69 | PriorityQueue edges = new PriorityQueue<>(new Comparator(){
70 | @Override
71 | public int compare(Edge e1, Edge e2) {
72 | return e1.weight < e2.weight ? -1 : 1;
73 | }
74 | });
75 | for (int i = 0; i < n; i++) {
76 | for (int j = i + 1; j < n; j++) {
77 | edges.offer(new Edge(i, j, Weight(x[i], y[i], x[j], y[j])));
78 | }
79 | }
80 | int unionNum = 0;
81 | while(!edges.isEmpty()){
82 | Edge currentEdge = edges.poll();
83 | int u = currentEdge.u;
84 | int v = currentEdge.v;
85 | if(Find(u, nodes) != Find(v, nodes)) {
86 | unionNum++;
87 | Union(u, v, nodes);
88 | }
89 | if(unionNum > n - k) return currentEdge.weight;
90 | }
91 | return -1.;
92 | }
93 |
94 | public static void main(String[] args) {
95 | Scanner scanner = new Scanner(System.in);
96 | int n = scanner.nextInt();
97 | int[] x = new int[n];
98 | int[] y = new int[n];
99 | for (int i = 0; i < n; i++) {
100 | x[i] = scanner.nextInt();
101 | y[i] = scanner.nextInt();
102 | }
103 | int k = scanner.nextInt();
104 | System.out.println(clustering(x, y, k));
105 | }
106 | }
107 |
108 |
--------------------------------------------------------------------------------
/week 5/clustering/clustering.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | using std::vector;
9 | using std::pair;
10 |
11 | struct node {
12 | int parent;
13 | int rank;
14 | int x;
15 | int y;
16 |
17 | node(int a, int b, int c = -1, int d = 0) {
18 | x = a;
19 | y = b;
20 | parent = c;
21 | rank = d;
22 | }
23 | };
24 |
25 | struct edge {
26 | int u;
27 | int v;
28 | double weight;
29 |
30 | edge(int a, int b, double c) {
31 | u = a;
32 | v = b;
33 | weight = c;
34 | }
35 | };
36 |
37 | bool cmp(edge a, edge b) {
38 | return a.weight < b.weight;
39 | }
40 |
41 | void make_set(int i, vector &nodes, vector &x, vector &y) {
42 | nodes.push_back(node(x[i], y[i], i));
43 | }
44 |
45 | double weight(int x1, int y1, int x2, int y2) {
46 | return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
47 | }
48 |
49 | int Find(int i, vector &nodes) {
50 | if (i != nodes[i].parent) {
51 | nodes[i].parent = Find(nodes[i].parent, nodes);
52 | }
53 | return nodes[i].parent;
54 | }
55 |
56 | void Union(int u, int v, vector &nodes) {
57 | int r1 = Find(u, nodes);
58 | int r2 = Find(v, nodes);
59 | if (r1 != r2) {
60 | if (nodes[r1].rank > nodes[r2].rank) {
61 | nodes[r2].parent = r1;
62 | } else {
63 | nodes[r1].parent = r2;
64 | if (nodes[r1].rank == nodes[r2].rank) {
65 | nodes[r2].rank++;
66 | }
67 | }
68 | }
69 | }
70 |
71 |
72 | double clustering(vector x, vector y, int k) {
73 | //write your code here
74 | int n = x.size();
75 | vector nodes;
76 | for (int i = 0; i < n; i++) {
77 | make_set(i, nodes, x, y);
78 | }
79 | vector edges;
80 | for (int i = 0; i < n; i++) {
81 | for (int j = i + 1; j < n; j++) {
82 | edges.push_back(edge(i, j, weight(x[i], y[i], x[j], y[j])));
83 | }
84 | }
85 | std::sort(edges.begin(), edges.end(), cmp);
86 | int union_num = 0;
87 | for (int i = 0; i < edges.size(); i++) {
88 | edge current_edge = edges[i];
89 | int u = current_edge.u;
90 | int v = current_edge.v;
91 | if (Find(u, nodes) != Find(v, nodes)) {
92 | union_num++;
93 | Union(u, v, nodes);
94 | }
95 | if(union_num > n - k) return current_edge.weight;
96 | }
97 | return -1.;
98 | }
99 |
100 | int main() {
101 | size_t n;
102 | int k;
103 | std::cin >> n;
104 | vector x(n), y(n);
105 | for (size_t i = 0; i < n; i++) {
106 | std::cin >> x[i] >> y[i];
107 | }
108 | std::cin >> k;
109 | std::cout << std::setprecision(10) << clustering(x, y, k) << std::endl;
110 | }
111 |
--------------------------------------------------------------------------------
/week 5/clustering/clustering.py:
--------------------------------------------------------------------------------
1 | #import sys
2 | import math
3 |
4 | class Node:
5 | def __init__(self, a, b, c):
6 | self.x = a
7 | self.y = b
8 | self.parent = c
9 | self.rank = 0
10 |
11 | class Edge:
12 | def __init__(self, a, b, c):
13 | self.u = a
14 | self.v = b
15 | self.weight = c
16 |
17 | def MakeSet(i, nodes, x, y):
18 | nodes.append(Node(x[i], y[i], i))
19 |
20 | def weight(x1, y1, x2, y2):
21 | return math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
22 |
23 | def Find(i, nodes):
24 | if (i != nodes[i].parent) :
25 | nodes[i].parent = Find(nodes[i].parent, nodes)
26 | return nodes[i].parent
27 |
28 | def Union(u, v, nodes):
29 | r1 = Find(u, nodes)
30 | r2 = Find(v, nodes)
31 | if (r1 != r2):
32 | if (nodes[r1].rank > nodes[r2].rank):
33 | nodes[r2].parent = r1
34 | else:
35 | nodes[r1].parent = r2
36 | if (nodes[r1].rank == nodes[r2].rank):
37 | nodes[r2].rank += 1
38 |
39 | def clustering(x, y, k):
40 | #write your code here
41 | n = len(x)
42 | nodes = []
43 | for i in range(n):
44 | MakeSet(i, nodes, x, y)
45 | edges = []
46 | for i in range(n):
47 | for j in range(i+1, n):
48 | edges.append(Edge(i, j, weight(x[i], y[i], x[j], y[j])))
49 | edges = sorted(edges, key=lambda edge: edge.weight)
50 | union_num = 0
51 | for edge in edges:
52 | if Find(edge.u, nodes) != Find(edge.v, nodes):
53 | union_num += 1
54 | Union(edge.u, edge.v, nodes)
55 | if(union_num > n - k):
56 | return edge.weight
57 | return -1.
58 |
59 |
60 | if __name__ == '__main__':
61 | n = int(raw_input())
62 | x = [0] * n
63 | y = [0] * n
64 | for i in range(n):
65 | x[i], y[i] = map(int, raw_input().split())
66 | k = int(raw_input())
67 | '''
68 | input = sys.stdin.read()
69 | data = list(map(int, input.split()))
70 | n = data[0]
71 | data = data[1:]
72 | x = data[0:2 * n:2]
73 | y = data[1:2 * n:2]
74 | data = data[2 * n:]
75 | k = data[0]
76 | '''
77 | print("{0:.9f}".format(clustering(x, y, k)))
78 |
--------------------------------------------------------------------------------
/week 5/connecting_points/ConnectingPoints.java:
--------------------------------------------------------------------------------
1 | import java.util.Scanner;
2 | import java.util.PriorityQueue;
3 | import java.util.Comparator;
4 |
5 | public class ConnectingPoints {
6 | private static class Node {
7 | int x;
8 | int y;
9 | int parent;
10 | int rank;
11 |
12 | public Node(int a, int b, int c) {
13 | x = a;
14 | y = b;
15 | parent = c;
16 | rank = 0;
17 | }
18 | }
19 |
20 | private static class Edge {
21 | int u;
22 | int v;
23 | double weight;
24 |
25 | public Edge(int a, int b, double c) {
26 | u = a;
27 | v = b;
28 | weight = c;
29 | }
30 | }
31 |
32 | private static void MakeSet(int i, Node[] nodes, int[] x, int[] y) {
33 | nodes[i] = new Node(x[i], y[i], i);
34 | }
35 |
36 | private static double Weight(int x1, int y1, int x2, int y2) {
37 | return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
38 | }
39 |
40 | private static int Find(int i, Node[] nodes) {
41 | if (i != nodes[i].parent) {
42 | nodes[i].parent = Find(nodes[i].parent, nodes);
43 | }
44 | return nodes[i].parent;
45 | }
46 |
47 | private static void Union(int u, int v, Node[] nodes) {
48 | int r1 = Find(u, nodes);
49 | int r2 = Find(v, nodes);
50 | if (r1 != r2) {
51 | if (nodes[r1].rank > nodes[r2].rank) {
52 | nodes[r2].parent = r1;
53 | } else {
54 | nodes[r1].parent = r2;
55 | if (nodes[r1].rank == nodes[r2].rank) {
56 | nodes[r2].rank++;
57 | }
58 | }
59 | }
60 | }
61 |
62 | private static double minimumDistance(int[] x, int[] y) {
63 | double result = 0.;
64 | //write your code here
65 | int n = x.length;
66 | Node[] nodes = new Node[n];
67 | for (int i = 0; i < n; i++) {
68 | MakeSet(i, nodes, x, y);
69 | }
70 | PriorityQueue edges = new PriorityQueue<>(new Comparator(){
71 | @Override
72 | public int compare(Edge e1, Edge e2) {
73 | return e1.weight < e2.weight ? -1 : 1;
74 | }
75 | });
76 | for (int i = 0; i < n; i++) {
77 | for (int j = i + 1; j < n; j++) {
78 | edges.offer(new Edge(i, j, Weight(x[i], y[i], x[j], y[j])));
79 | }
80 | }
81 | while (!edges.isEmpty()) {
82 | Edge currentEdge = edges.poll();
83 | int u = currentEdge.u;
84 | int v = currentEdge.v;
85 | if (Find(u, nodes) != Find(v, nodes)) {
86 | result += currentEdge.weight;
87 | Union(u, v, nodes);
88 | }
89 | }
90 |
91 | return result;
92 | }
93 |
94 | public static void main(String[] args) {
95 | Scanner scanner = new Scanner(System.in);
96 | int n = scanner.nextInt();
97 | int[] x = new int[n];
98 | int[] y = new int[n];
99 | for (int i = 0; i < n; i++) {
100 | x[i] = scanner.nextInt();
101 | y[i] = scanner.nextInt();
102 | }
103 | System.out.println(minimumDistance(x, y));
104 | }
105 | }
106 |
107 |
--------------------------------------------------------------------------------
/week 5/connecting_points/connecting_points.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | using std::vector;
8 |
9 | struct node {
10 | int parent;
11 | int rank;
12 | int x;
13 | int y;
14 |
15 | node(int a, int b, int c = -1, int d = 0) {
16 | x = a;
17 | y = b;
18 | parent = c;
19 | rank = d;
20 | }
21 | };
22 |
23 | struct edge {
24 | int u;
25 | int v;
26 | double weight;
27 |
28 | edge(int a, int b, double c) {
29 | u = a;
30 | v = b;
31 | weight = c;
32 | }
33 | };
34 |
35 | bool cmp(edge a, edge b) {
36 | return a.weight < b.weight;
37 | }
38 |
39 | void make_set(int i, vector &nodes, vector &x, vector &y) {
40 | nodes.push_back(node(x[i], y[i], i));
41 | }
42 |
43 | double weight(int x1, int y1, int x2, int y2) {
44 | return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
45 | }
46 |
47 | int Find(int i, vector &nodes) {
48 | if (i != nodes[i].parent) {
49 | nodes[i].parent = Find(nodes[i].parent, nodes);
50 | }
51 | return nodes[i].parent;
52 | }
53 |
54 | void Union(int u, int v, vector &nodes) {
55 | int r1 = Find(u, nodes);
56 | int r2 = Find(v, nodes);
57 | if (r1 != r2) {
58 | if (nodes[r1].rank > nodes[r2].rank) {
59 | nodes[r2].parent = r1;
60 | } else {
61 | nodes[r1].parent = r2;
62 | if (nodes[r1].rank == nodes[r2].rank) {
63 | nodes[r2].rank++;
64 | }
65 | }
66 | }
67 | }
68 |
69 | double minimum_distance(vector x, vector y) {
70 | double result = 0.;
71 | //write your code here
72 | int n = x.size();
73 | vector nodes;
74 | for (int i = 0; i < n; i++) {
75 | make_set(i, nodes, x, y);
76 | }
77 | vector edges;
78 | for (int i = 0; i < n; i++) {
79 | for (int j = i + 1; j < n; j++) {
80 | edges.push_back(edge(i, j, weight(x[i], y[i], x[j], y[j])));
81 | }
82 | }
83 | std::sort(edges.begin(), edges.end(), cmp);
84 | for (int i = 0; i < edges.size(); i++) {
85 | edge current_edge = edges[i];
86 | int u = current_edge.u;
87 | int v = current_edge.v;
88 | if (Find(u, nodes) != Find(v, nodes)) {
89 | result += current_edge.weight;
90 | Union(u, v, nodes);
91 | }
92 | }
93 | return result;
94 | }
95 |
96 | int main() {
97 | size_t n;
98 | std::cin >> n;
99 | vector x(n), y(n);
100 | for (size_t i = 0; i < n; i++) {
101 | std::cin >> x[i] >> y[i];
102 | }
103 | std::cout << std::setprecision(10) << minimum_distance(x, y) << std::endl;
104 | }
105 |
--------------------------------------------------------------------------------
/week 5/connecting_points/connecting_points.py:
--------------------------------------------------------------------------------
1 | #import sys
2 | import math
3 |
4 | class Node:
5 | def __init__(self, a, b, c):
6 | self.x = a
7 | self.y = b
8 | self.parent = c
9 | self.rank = 0
10 |
11 | class Edge:
12 | def __init__(self, a, b, c):
13 | self.u = a
14 | self.v = b
15 | self.weight = c
16 |
17 | def MakeSet(i, nodes, x, y):
18 | nodes.append(Node(x[i], y[i], i))
19 |
20 | def weight(x1, y1, x2, y2):
21 | return math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
22 |
23 | def Find(i, nodes):
24 | if (i != nodes[i].parent) :
25 | nodes[i].parent = Find(nodes[i].parent, nodes)
26 | return nodes[i].parent
27 |
28 | def Union(u, v, nodes):
29 | r1 = Find(u, nodes)
30 | r2 = Find(v, nodes)
31 | if (r1 != r2):
32 | if (nodes[r1].rank > nodes[r2].rank):
33 | nodes[r2].parent = r1
34 | else:
35 | nodes[r1].parent = r2
36 | if (nodes[r1].rank == nodes[r2].rank):
37 | nodes[r2].rank += 1
38 |
39 | def minimum_distance(x, y):
40 | result = 0.
41 | #write your code here
42 | n = len(x)
43 | nodes = []
44 | for i in range(n):
45 | MakeSet(i, nodes, x, y)
46 | edges = []
47 | for i in range(n):
48 | for j in range(i+1, n):
49 | edges.append(Edge(i, j, weight(x[i], y[i], x[j], y[j])))
50 | edges = sorted(edges, key=lambda edge: edge.weight)
51 | for edge in edges:
52 | if Find(edge.u, nodes) != Find(edge.v, nodes):
53 | result += edge.weight
54 | Union(edge.u, edge.v, nodes)
55 | return result
56 |
57 |
58 | if __name__ == '__main__':
59 | n = int(raw_input())
60 | x = [0] * n
61 | y = [0] * n
62 | for i in range(n):
63 | x[i], y[i] = map(int, raw_input().split())
64 | '''
65 | input = sys.stdin.read()
66 | data = list(map(int, input.split()))
67 | n = data[0]
68 | x = data[1::2]
69 | y = data[2::2]
70 | '''
71 | print("{0:.9f}".format(minimum_distance(x, y)))
72 |
--------------------------------------------------------------------------------
/week 5/spanning_trees_problems.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akueisara/algo-on-graphs/06c71e9558838a982b624606cd0b5e7def0fd99e/week 5/spanning_trees_problems.pdf
--------------------------------------------------------------------------------
/week 6/Advanced-Shortest-Paths.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akueisara/algo-on-graphs/06c71e9558838a982b624606cd0b5e7def0fd99e/week 6/Advanced-Shortest-Paths.pdf
--------------------------------------------------------------------------------
/week 6/dist_with_coords/DistWithCoords.java:
--------------------------------------------------------------------------------
1 | // Failed case #6/9: Wrong answer .. don't know why..
2 |
3 | import java.util.Scanner;
4 | import java.util.ArrayList;
5 | import java.util.Arrays;
6 | import java.util.PriorityQueue;
7 | import java.util.HashMap;
8 | import java.lang.Math;
9 |
10 | public class DistWithCoords {
11 | private static class Impl {
12 | // Number of nodes
13 | int n;
14 | // Coordinates of nodes
15 | int[] x;
16 | int[] y;
17 | // See description of these fields in the starters for friend_suggestion
18 | ArrayList[] adj;
19 | ArrayList[] cost;
20 | Long[] distance;
21 | PriorityQueue queue;
22 | boolean[] visited;
23 | ArrayList workset;
24 | HashMap p;
25 | final Long INFINITY = Long.MAX_VALUE / 4;
26 |
27 | Impl(int n) {
28 | this.n = n;
29 | visited = new boolean[n];
30 | x = new int[n];
31 | y = new int[n];
32 | Arrays.fill(visited, false);
33 | workset = new ArrayList();
34 | p = new HashMap();
35 | distance = new Long[n];
36 | for (int i = 0; i < n; ++i) {
37 | distance[i] = INFINITY;
38 | }
39 | queue = new PriorityQueue();
40 | }
41 |
42 | // See the description of this method in the starters for friend_suggestion
43 | void clear() {
44 | for (int v : workset) {
45 | distance[v] = INFINITY;
46 | visited[v] = false;
47 | }
48 | workset.clear();
49 | queue.clear();
50 | p.clear();
51 | }
52 |
53 | // See the description of this method in the starters for friend_suggestion
54 | void visit(int v, Long dist, Long measure) {
55 | // Implement this method yourself
56 | if (distance[v] > dist) {
57 | distance[v] = dist;
58 | queue.add(new Entry(distance[v] + measure, v));
59 | workset.add(v);
60 | }
61 | }
62 |
63 | Long potential(int u, int t) {
64 | if (!p.containsKey(u)) {
65 | p.put(u, (long) Math.sqrt((x[u]-x[t])*(x[u]-x[t])+(y[u]-y[t])*(y[u]-y[t])));
66 | }
67 | return p.get(u);
68 | }
69 |
70 | int extractMin() {
71 | Entry e = queue.poll();
72 | return e.node;
73 | }
74 |
75 | void process(int u, int t, ArrayList[] adj, ArrayList[] cost) {
76 | for (int i = 0; i < adj[u].size(); ++i) {
77 | int v = adj[u].get(i);
78 | if (visited[v] != true) {
79 | Long w = (long) cost[u].get(i);
80 | visit(v, distance[u] + w, potential(v, t));
81 | }
82 | }
83 | }
84 |
85 | // Returns the distance from s to t in the graph.
86 | Long query(int s, int t) {
87 | clear();
88 | visit(s, 0L, potential(s, t));
89 | // Implement the rest of the algorithm yourself
90 | while (!queue.isEmpty()) {
91 | int v = extractMin();
92 | if (v == t) {
93 | if(distance[t] != INFINITY)
94 | return distance[t];
95 | else
96 | return -1L;
97 | }
98 | if (visited[v] != true) {
99 | process(v, t, adj, cost);
100 | visited[v] = true;
101 | }
102 | }
103 | return -1L;
104 | }
105 |
106 | class Entry implements Comparable
107 | {
108 | Long cost;
109 | int node;
110 |
111 | public Entry(Long cost, int node)
112 | {
113 | this.cost = cost;
114 | this.node = node;
115 | }
116 |
117 | public int compareTo(Entry other)
118 | {
119 | return cost < other.cost ? -1 : cost > other.cost ? 1 : 0;
120 | }
121 | }
122 | }
123 |
124 | public static void main(String args[]) {
125 | Scanner in = new Scanner(System.in);
126 | int n = in.nextInt();
127 | int m = in.nextInt();
128 | Impl DistWithCoords = new Impl(n);
129 | DistWithCoords.adj = (ArrayList[])new ArrayList[n];
130 | DistWithCoords.cost = (ArrayList[])new ArrayList[n];
131 | for (int i = 0; i < n; i++) {
132 | DistWithCoords.adj[i] = new ArrayList();
133 | DistWithCoords.cost[i] = new ArrayList();
134 | }
135 |
136 | for (int i = 0; i < n; i++) {
137 | int x, y;
138 | x = in.nextInt();
139 | y = in.nextInt();
140 | DistWithCoords.x[i] = x;
141 | DistWithCoords.y[i] = y;
142 | }
143 |
144 | for (int i = 0; i < m; i++) {
145 | int x, y, c;
146 | x = in.nextInt();
147 | y = in.nextInt();
148 | c = in.nextInt();
149 | DistWithCoords.adj[x - 1].add(y - 1);
150 | DistWithCoords.cost[x - 1].add(c);
151 | }
152 |
153 | int t = in.nextInt();
154 |
155 | for (int i = 0; i < t; i++) {
156 | int u, v;
157 | u = in.nextInt();
158 | v = in.nextInt();
159 | System.out.println(DistWithCoords.query(u-1, v-1));
160 | }
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/week 6/dist_with_coords/dist_with_coords.cpp:
--------------------------------------------------------------------------------
1 | // Failed case #9/9: unknown signal 11... don't know how to slove it QQ
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include