알고리즘 : SCC

Strongly Connected Component

시간 제한 메모리 제한
2초 512 MB

 

 

문제

방향 그래프가 주어졌을 때, 그 그래프를 SCC들로 나누는 프로그램을 작성하시오.

방향 그래프의 SCC는 우선 정점의 최대 부분집합이며, 그 부분집합에 들어있는 서로 다른 임의의 두 정점 u, v에 대해서 u에서 v로 가는 경로와 v에서 u로 가는 경로가 모두 존재하는 경우를 말한다.

예를 들어 위와 같은 그림을 보자. 이 그래프에서 SCC들은 {a, b, e}, {c, d}, {f, g}, {h} 가 있다. 물론 h에서 h로 가는 간선이 없는 경우에도 {h}는 SCC를 이룬다.

 

입력

첫째 줄에 두 정수 V(1 ≤ V ≤ 10,000), E(1 ≤ E ≤ 100,000)가 주어진다. 이는 그래프가 V개의 정점과 E개의 간선으로 이루어져 있다는 의미이다. 다음 E개의 줄에는 간선에 대한 정보를 나타내는 두 정수 A, B가 주어진다. 이는 A번 정점과 B번 정점이 연결되어 있다는 의미이다. 이때 방향은 A → B가 된다.

정점은 1부터 V까지 번호가 매겨져 있다.

 

출력

첫째 줄에 SCC의 개수 K를 출력한다. 다음 K개의 줄에는 각 줄에 하나의 SCC에 속한 정점의 번호를 출력한다. 각 줄의 끝에는 -1을 출력하여 그 줄의 끝을 나타낸다. 각각의 SCC를 출력할 때 그 안에 속한 정점들은 오름차순으로 출력한다. 또한 여러 개의 SCC에 대해서는 그 안에 속해있는 가장 작은 정점의 정점 번호 순으로 출력한다.

 

 

예제 입력 1

7 9
1 4
4 5
5 1
1 6
6 7
2 7
7 3
3 7
7 2

 

예제 입력 2

3
1 4 5 -1
2 3 7 -1
6 -1

 

풀이

SCC : https://www.youtube.com/watch?v=M9d_DthAxwg 

 

import java.io.*;
import java.util.*;

public class Main {
    static ArrayList<Integer>[] route;
    static ArrayList<Integer>[] reverseRoute;
    static ArrayList<ArrayList<Integer>> answerList = new ArrayList<>();
    
    static boolean[] visited;
    static int[] numCnts;
    
    static int numCnt = 1;
    
    private static void dfs(int cur) {
        for(int next: route[cur]) {
            if(!visited[next]) {
                visited[next] = true;
                dfs(next);
            }
        }
        numCnts[numCnt++] = cur;
    }
    
    private static void dfs2(int cur) {
        answerList.get(answerList.size() - 1).add(cur);
        for(int next: reverseRoute[cur]) {
            if(!visited[next]) {
                visited[next] = true;
                dfs2(next);
            }
        }
    }
    
    @SuppressWarnings("unchecked")
    public static void main(String args[]) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        int V = Integer.parseInt(st.nextToken());
        int E = Integer.parseInt(st.nextToken());
        
        route = new ArrayList[V+1];
        reverseRoute = new ArrayList[V+1];
        
        for(int i = 1; i <= V; i++) {
            route[i] = new ArrayList<>();
            reverseRoute[i] = new ArrayList<>();
        }
        
        visited = new boolean[V+1];
        numCnts = new int[V+1];

        for(int i=1; i <= E; i++) {
            st = new StringTokenizer(br.readLine());
            int from = Integer.parseInt(st.nextToken());
            int to = Integer.parseInt(st.nextToken());
            route[from].add(to);
            reverseRoute[to].add(from);
        }
        
        // DFS를 하면서, 빠져나오는 순서대로 시간을 기록
        for(int i=1; i <= V; i++) {
            if(!visited[i]) {
                visited[i] = true;
                dfs(i);
            }
        }
        
        visited = new boolean[V+1];
        
        // 뒤집은 그래프에 대해서, 빠져나오는 시간이 큰 노느부터 순회
        // 이 때 만나는 노드들이 모두 같은 그룹임.
        for(int i=V; i>= 1; i--) {
            if(!visited[numCnts[i]]) {
                visited[numCnts[i]] = true;
                answerList.add(new ArrayList<Integer>());
                dfs2(numCnts[i]);
            }
        }
        
        for(ArrayList<Integer> next: answerList) {
            Collections.sort(next);
        }
        
        answerList.sort((o1, o2) -> o1.get(0) - o2.get(0));
        
        System.out.println(answerList.size());
        for(int i=0; i < answerList.size(); i++) {
            for(int next: answerList.get(i)) {
                System.out.print(next + " ");
            }
            System.out.println("-1");
        }
    }
}

출처

'알고리즘' 카테고리의 다른 글

BFS/미로 탈출 백준 14923번  (2) 2023.10.28
그래프/파티 백준 1238번  (0) 2023.10.04
DP/1,2,3 더하기 백준 9095번  (0) 2022.10.09
DFS/웜바이러스 백준 2606번  (0) 2022.02.28
스택/괄호의값 백준 2504번  (0) 2022.02.13
알고리즘 : 문자열

큰 수 A+B

시간 제한 메모리 제한
1초 256MB

 

문제

두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 A와 B가 주어진다. (0 < A,B < 1010000)

출력

첫째 줄에 A+B를 출력한다.

예제 입력 1

9223372036854775807 9223372036854775808

예제 출력 1

18446744073709551615

출처


import java.io.*;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) throws Exception {
		Main main = new Main();
		main.start();
	}

	private void start() throws Exception {
		//System.setIn(new FileInputStream("src/test1/input.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		String in = br.readLine();
		StringTokenizer st = new StringTokenizer(in, " ");
		String num1 = st.nextToken();
		String num2 = st.nextToken();
		bw.write(add(num1, num2));
		br.close();
		bw.close();
	}

	private String add(String num1, String num2) {
		//System.out.println(String.format("%s + %s", num1, num2));
		int f = 0;
		StringBuffer result = new StringBuffer();
		for (int i = num1.length() - 1, j = num2.length() - 1; i >= 0 || j >= 0; i--, j--) {
			int target1 = i < 0 ? 0 : num1.charAt(i) - '0';
			int target2 = j < 0 ? 0 : num2.charAt(j) - '0';
			int addResult = target1 + target2 + f;
			//System.out.println(String.format("%d + %d = %d", target1, target2, addResult));
			result.insert(0, addResult % 10);
			f = addResult / 10;
		}
		if(f > 0) {
			result.insert(0, f);
		}
		return result.toString();
	}
}

 

시간 메모리
152ms 15024KB

 


출처

- https://www.acmicpc.net/problem/10757

알고리즘 : 정렬

나이순 정렬

시간 제한 메모리 제한
3초 256MB

문제

온라인 저지에 가입한 사람들의 나이와 이름이 가입한 순서대로 주어진다. 이때, 회원들을 나이가 증가하는 순으로, 나이가 같으면 먼저 가입한 사람이 앞에 오는 순서로 정렬하는 프로그램을 작성하시오.

입력

첫째 줄에 온라인 저지 회원의 수 N이 주어진다. (1 ≤ N ≤ 100,000)

둘째 줄부터 N개의 줄에는 각 회원의 나이와 이름이 공백으로 구분되어 주어진다. 나이는 1보다 크거나 같으며, 200보다 작거나 같은 정수이고, 이름은 알파벳 대소문자로 이루어져 있고, 길이가 100보다 작거나 같은 문자열이다. 입력은 가입한 순서로 주어진다.

출력

첫째 줄부터 총 N개의 줄에 걸쳐 온라인 저지 회원을 나이 순, 나이가 같으면 가입한 순으로 한 줄에 한 명씩 나이와 이름을 공백으로 구분해 출력한다.

예제 입력 1

3
21 Junkyu
21 Dohyun
20 Sunyoung

예제 출력 1

20 Sunyoung
21 Junkyu
21 Dohyun

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

public class Main {
	private int N;
	private List<User> users = new ArrayList<User>();
	class User implements Comparable<User>{
		private int age;
		private String name;
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		User(int age, String name) {
			this.age = age;
			this.name = name;
		}
		@Override
		public int compareTo(User o) {
            return this.age - o.getAge();
		}
		
	}
	public static void main(String[] args) throws Exception{
		Main main = new Main();
		main.start();
	}
	public void start() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		N = Integer.parseInt(br.readLine());
		for(int i=0;i<N;i++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			User user = new User(Integer.parseInt(st.nextToken()), st.nextToken());
			users.add(user);
		}
		
		Collections.sort(users);
		for(User user:users) {
			System.out.println(String.format("%d %s", user.getAge(), user.getName()));
		}
		br.close();
	}
}

출처

- https://www.acmicpc.net/problem/10814

 

알고리즘 : 문자열

시간 제한 메모리 제한
1초 256MB

문제

알파벳 소문자로만 이루어진 단어가 주어진다. 이때, 이 단어가 팰린드롬인지 아닌지 확인하는 프로그램을 작성하시오.

팰린드롬이란 앞으로 읽을 때와 거꾸로 읽을 때 똑같은 단어를 말한다. 

level, noon은 팰린드롬이고, baekjoon, online, judge는 팰린드롬이 아니다.

입력

첫째 줄에 단어가 주어진다. 단어의 길이는 1보다 크거나 같고, 100보다 작거나 같으며, 알파벳 소문자로만 이루어져 있다.

출력

첫째 줄에 팰린드롬이면 1, 아니면 0을 출력한다.

예제 입력 1 복사

level

예제 출력 1 복사

1

예제 입력 2 복사

baekjoon

예제 출력 2 복사

0

출처

 


 

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
	private String in;
	
	public static void main(String[] args) throws Exception {
		Main main = new Main();
		main.start();
	}
	public void start() throws Exception {
		//System.setIn(new FileInputStream("src/test2/input.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		in = br.readLine();
		
		System.out.println(checkPalindrome(0, in.length()-1) == 1 ? 1 : 0);
		br.close();
	}
	private int checkPalindrome(int from, int to) {
		if(from >= to) return 1;
		//System.out.println(String.format("%s %s == %s",in.charAt(from), in.charAt(to), in.charAt(from) == in.charAt(to)));
		if(in.charAt(from) == in.charAt(to)) {
			return checkPalindrome(from+1, to-1) * 1;
		}else {
			return 0;
		}
	}
}

 

시간 메모리 제한
128ms 14188

 


출처

- https://www.acmicpc.net/problem/10988

+ Recent posts