728x90
728x90

문제 링크 : https://www.acmicpc.net/problem/1774

 

1774번: 우주신과의 교감

(1,1) (3,1) (2,3) (4,3) 이렇게 우주신들과 황선자씨의 좌표가 주어졌고 1번하고 4번이 연결되어 있다. 그렇다면 1번하고 2번을 잇는 통로를 만들고 3번하고 4번을 잇는 통로를 만들면 신들과 선자씨끼

www.acmicpc.net

 

 

문제

황선자씨는 우주신과 교감을 할수 있는 채널러 이다. 하지만 우주신은 하나만 있는 것이 아니기때문에 황선자 씨는 매번 여럿의 우주신과 교감하느라 힘이 든다. 이러던 와중에 새로운 우주신들이 황선자씨를 이용하게 되었다.

하지만 위대한 우주신들은 바로 황선자씨와 연결될 필요가 없다. 이미 황선자씨와 혹은 이미 우주신끼리 교감할 수 있는 우주신들이 있기 때문에 새로운 우주신들은 그 우주신들을 거쳐서 황선자 씨와 교감을 할 수 있다.

우주신들과의 교감은 우주신들과 황선자씨 혹은 우주신들 끼리 이어진 정신적인 통로를 통해 이루어 진다. 하지만 우주신들과 교감하는 것은 힘든 일이기 때문에 황선자씨는 이런 통로들이 긴 것을  좋아하지 않는다. 왜냐하면 통로들이 길 수록 더 힘이 들기 때문이다.

또한 우리들은 3차원 좌표계로 나타낼 수 있는 세상에 살고 있지만 우주신들과 황선자씨는 2차원 좌표계로 나타낼 수 있는 세상에 살고 있다. 통로들의 길이는 2차원 좌표계상의 거리와 같다.

이미 황선자씨와 연결된, 혹은 우주신들과 연결된 통로들이 존재한다. 우리는 황선자 씨를 도와 아직 연결이 되지 않은 우주신들을 연결해 드려야 한다. 새로 만들어야 할 정신적인 통로의 길이들이 합이 최소가 되게 통로를 만들어 “빵상”을 외칠수 있게 도와주자.

입력

첫째 줄에 우주신들의 개수(N<=1,000) 이미 연결된 신들과의 통로의 개수(M<=1,000)가 주어진다.

두 번째 줄부터 N개의 줄에는 황선자를 포함하여 우주신들의 좌표가 (0<= X<=1,000,000), (0<=Y<=1,000,000)가 주어진다. 그 밑으로 M개의 줄에는 이미 연결된 통로가 주어진다. 번호는 위의 입력받은 좌표들의 순서라고 생각하면 된다. 좌표는 정수이다.

출력

첫째 줄에 만들어야 할 최소의 통로 길이를 출력하라. 출력은 소수점 둘째짜리까지 출력하여라.

 

 


 

 

접근 방법

1) 먼저 이미 연결된 M개의 통로에 대해, 이미 연결되었다는 것을 표시하기 위해 노드의 부모 정보를 바꿔준다.

 

2) DFS 함수를 돌려서(중복조합) N개의 우주신 중 2개를 고르고, 우주신 사이의 거리를 구해서 edgeList에 저장한다. 

 

3) edgeList를 거리가 짧은 순으로 정렬한다.

 

4) edgeList에서 통로의 길이와 통로 양쪽에 연결된 우주신 정보를 꺼낸 후 길이가 짧은 순으로 MST를 만들어 나간다.

 

import java.util.*;

class Pair1774{		//해당 노드의 좌표 정보 
	Integer x, y;
	public Pair1774(Integer _x, Integer _y) {
		this.x = _x; 
		this.y = _y;
	}
	public Integer getX() {
		return this.x;
	}
	public Integer getY() {
		return this.y;
	}
}

class Edge1774{		// 통로의 길이와 통로에 연결된 우주신이 몇번째 우주신인지 
	Double dis;
	Integer v1,v2;
	public Edge1774(Double _dis, Integer _v1, Integer _v2) {
		this.dis = _dis;
		this.v1 = _v1;
		this.v2 = _v2;
	}
	public double getDis() {
		return this.dis;
	}
	public Integer getV1() {
		return this.v1;
	}
	public Integer getV2() {
		return this.v2;
	}
}
class Cmp1774 implements Comparator<Edge1774>{
	@Override
	public int compare(Edge1774 e1, Edge1774 e2) {
		if(e1.getDis() < e2. getDis()) return -1;
		else if(e1.getDis() > e2. getDis()) return 1;
		else return 0;
	}
}

public class MST_BOJ1774_우주신과의교감 {
	static Scanner sc = new Scanner(System.in);
	static int N, M;
	static Pair1774[] info = new Pair1774[1001];
	static int[] parent = new int[1001];
	static int[] visited = new int[1001];
	static ArrayList<Edge1774> edgeList = new ArrayList<Edge1774>();
	static double ans;
	static ArrayList<Integer> tmpList = new ArrayList<Integer>();

	//두 점 사이의 거리 리턴. 
	static public double getDistance(int v1, int v2) {
		int x1 = info[v1].getX();
		int y1 = info[v1].getY();
		int x2 = info[v2].getX();
		int y2 = info[v2].getY();

		double res = Math.sqrt(Math.pow((x1-x2), 2) + Math.pow((y1-y2), 2));
		return res;
	}
	
	
	static public int getParent(int x) {
		if(x==parent[x]) return x;
		else return getParent(parent[x]);
	}
	

	//N개 중 2개의 노드 픽 
	public static void pickDFS(int toPick, int start) {
		if(toPick==0) {
			int v1 = tmpList.get(0);
			int v2 = tmpList.get(1);
			double distance = getDistance(v1, v2);
			edgeList.add(new Edge1774(distance, v1, v2));
			return;
		}
		
		for(int i = start; i<=N; i++) {
			if(visited[i]==0) {
				visited[i] = 1;
				tmpList.add(i);
				pickDFS(toPick-1, i);
				tmpList.remove(tmpList.size()-1);
				visited[i] = 0;
			}
		}
		
	}
	
	
	public static void main(String[] args) {
		
		N = sc.nextInt();
		M = sc.nextInt();
		ans = 0;
		
		for(int i = 1; i<=N; i++) {
			int x = sc.nextInt();
			int y = sc.nextInt();
			info[i] = new Pair1774(x,y);
			parent[i] = i;
		}
		
		//이미 연결된 통로 표시 
		for(int i = 0; i<M; i++) {
			int v1 = sc.nextInt();
			int v2 = sc.nextInt();
			if(v1>v2) {
				int tmp = v1;
				v1 = v2;
				v2 = tmp;
			}
			int p1 = getParent(v1);
			int p2 = getParent(v2);
			if(p1!=p2) {
				parent[p2] = p1;
			}
		}
		
		pickDFS(2, 1);	// 2개를 골라서 edgeList에 간선(거리) 정보 저장 
		
		edgeList.sort(new Cmp1774());

		for(int i = 0; i<edgeList.size(); i++) {
			int v1 = edgeList.get(i).getV1();
			int v2 = edgeList.get(i).getV2();
			int p1 = getParent(v1);
			int p2 = getParent( v2);
			if(p1 != p2) {
				parent[p2] = p1;
				ans += getDistance(v1, v2);
			}
		}
		
		System.out.printf("%.2f",ans);
	}
}

728x90
728x90

문제 링크 : https://www.acmicpc.net/problem/1922

 

1922번: 네트워크 연결

이 경우에 1-3, 2-3, 3-4, 4-5, 4-6을 연결하면 주어진 output이 나오게 된다.

www.acmicpc.net

 

 

문제

도현이는 컴퓨터와 컴퓨터를 모두 연결하는 네트워크를 구축하려 한다. 하지만 아쉽게도 허브가 있지 않아 컴퓨터와 컴퓨터를 직접 연결하여야 한다. 그런데 모두가 자료를 공유하기 위해서는 모든 컴퓨터가 연결이 되어 있어야 한다. (a와 b가 연결이 되어 있다는 말은 a에서 b로의 경로가 존재한다는 것을 의미한다. a에서 b를 연결하는 선이 있고, b와 c를 연결하는 선이 있으면 a와 c는 연결이 되어 있다.)

그런데 이왕이면 컴퓨터를 연결하는 비용을 최소로 하여야 컴퓨터를 연결하는 비용 외에 다른 곳에 돈을 더 쓸 수 있을 것이다. 이제 각 컴퓨터를 연결하는데 필요한 비용이 주어졌을 때 모든 컴퓨터를 연결하는데 필요한 최소비용을 출력하라. 모든 컴퓨터를 연결할 수 없는 경우는 없다.

입력

첫째 줄에 컴퓨터의 수 N (1 ≤ N ≤ 1000)가 주어진다.

둘째 줄에는 연결할 수 있는 선의 수 M (1 ≤ M ≤ 100,000)가 주어진다.

셋째 줄부터 M+2번째 줄까지 총 M개의 줄에 각 컴퓨터를 연결하는데 드는 비용이 주어진다. 이 비용의 정보는 세 개의 정수로 주어지는데, 만약에 a b c 가 주어져 있다고 하면 a컴퓨터와 b컴퓨터를 연결하는데 비용이 c (1 ≤ c ≤ 10,000) 만큼 든다는 것을 의미한다. a와 b는 같을 수도 있다.

출력

모든 컴퓨터를 연결하는데 필요한 최소비용을 첫째 줄에 출력한다.

 

 

 


 

 

접근 방법

1197번 최소 스패닝 트리 문제와 동일한 방식이다.

받은 간선 정보를 비용을 기준으로 오름차순 정렬한 뒤, 모든 간선에 대해 검사한다.

해당 간선 양쪽에 연결된 노드의 부모를 찾아서 부모가 다른 경우에만 연결해준다. (cost를 더한다)

부모가 같은 경우는 이미 연결된 것을 의미한다.

 

 

주의할 점

간선에 연결된 노드를 검사할 때, 해당 간선에 연결된 노드 v1, v2에 대해 v2의 부모를 v1으로 설정하는 것이 아니라(parent[v2]=v1) 

v2의 부모의 부모를 v2의 부모로 설정하는 것이다. (parent[p1] = p2)

 

import java.util.*;


class Pair1922{
	Integer cost, v1, v2;
	public Pair1922(Integer _cost, Integer _v1, Integer _v2) {
		this.cost = _cost;
		this.v1 = _v1;
		this.v2 = _v2;
	}
	public Integer getCost() {
		return this.cost;
	}
	public Integer getv1() {
		return this.v1;
	}
	public Integer getv2() {
		return this.v2;
	}
}

class Cmp1922 implements Comparator<Pair1922>{
	@Override
	public int compare(Pair1922 p1, Pair1922 p2) {
		if(p1.getCost() < p2.getCost()) return -1;
		else if(p1.getCost() > p2.getCost()) return 1;
		else return 0;
	}
}


public class MST_BOJ1922_네트워크연결 {

	static int[] parent = new int[1001];
	static int getParent(int x) {
		if(x==parent[x]) return x;
		else return parent[x] = getParent(parent[x]);
	}

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		ArrayList<Pair1922> listInfo = new ArrayList<Pair1922>();
		
		int N = sc.nextInt();
		int M = sc.nextInt();
		
		int ans = 0;
		
		for(int i = 0; i<=N; i++) {
			parent[i] = i;
		}

		for(int i = 0; i<M; i++) {
			int a = sc.nextInt();
			int b = sc.nextInt();
			int cost = sc.nextInt();
			
			listInfo.add(new Pair1922(cost, a, b));	
		}
		
		if(listInfo.size()==1 && listInfo.get(0).getv1()==listInfo.get(0).getv2()) {
			ans = listInfo.get(0).getCost();
		}
		
		else {
			listInfo.sort(new Cmp1922());
			
			for(int i = 0; i<listInfo.size(); i++) {
				int v1 = listInfo.get(i).getv1();
				int v2 =  listInfo.get(i).getv2();
				int p1 = getParent(v1);
				int p2 = getParent(v2);
				System.out.println(p1 + " " + p2);
				if(p1==p2) continue;
				else {
					parent[p2] = p1;
					int e = listInfo.get(i).getCost();
					ans += e;
				}	
			}
		}
		
		System.out.println(ans);
		
		
	}
}

728x90

+ Recent posts