본문 바로가기

알고리즘/백준

백준 2610 회의준비

https://www.acmicpc.net/problem/2610

 

2610번: 회의준비

첫째 중에 회의에 참석하는 사람의 수 N이 주어진다. 참석자들은 1부터 N까지의 자연수로 표현되며 회의에 참석하는 인원은 100 이하이다. 둘째 줄에는 서로 알고 있는 관계의 수 M이 주어진다. 이

www.acmicpc.net

플로이드 워셜 알고리즘과 약간의 구현이 필요한 문제이다.

 

floyd에서 dp를 구하고 이를 활용해서 각 그룹의 대표와 그 그룹의 최대값이자 최솟값(?)을 구했다.

 

 

/* 회의준비 */
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>

#define ll long long int
#define pp pair<ll,ll>
#define INF 2100000000

using namespace std;

void input();
void solve();

int N, M;
bool is_visit[101];
vector<ll> answer;
ll dp[110][110];

int main(void) {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	fill(&dp[0][0], &dp[110 - 1][110], INF);
	
	input(); solve();
	return 0;
}

void input() {
	cin >> N >> M;
	for (int i = 0; i < M; i++) {
		int a, b; cin >> a >> b;
		dp[a][b] = 1;
		dp[b][a] = 1;
	}

	for (int i = 1; i <= N; i++) {
		dp[i][i] = 0;
	}
	return;
}

void floyd() {
	for (int k = 1; k <= N; k++) {
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				if (dp[i][j] > dp[i][k] + dp[k][j]) {
					dp[i][j] = dp[i][k] + dp[k][j];
				}
			}
		}
	}

	return;
}

void representation() {

	queue<int> q;

	for (int i = 1; i <= N; i++) {
		// 이미 방문한 노드는 다른 그룹에 속해있으니 패스. 
		if (is_visit[i] == true) continue;

		// 아직 방문하지 않았으니 새로운 그룹을 형성할 수 있다. 
		is_visit[i] = true;

		q.push(i);
		// maxi는 현재 그룹의 최솟값, idx는 그 최솟값의 번호
		ll maxi = INF, idx = i;

		while (!q.empty()) {
			//t_maxi는 현재 노드의 최댓값
			// 이 최댓값들 중 최솟값을 구하는 게 이 문제의 핵심
			ll curr = q.front(), t_maxi = 0;
			q.pop();

			// 이걸로 현재 노드가 갈 수 있는 모든 weight를 구한다. 
			for (int j = 1; j <= N; j++) {
				// 현재 노드와 같으면 계산하지 않아도 된다.
				if (j == curr) continue;

				// 아직 방문하지 않은 노드고 현재 노드와 연결되어 있는 노드라면
				if (dp[curr][j] != INF && is_visit[j] == false) {
					// 방문체크하고 큐에 삽입한다. 
					is_visit[j] = true;
					q.push(j);
				}

				// 방문여부와 상관없이 현재 노드(curr)와 연결된 모든 weight 중 최댓값을 찾는다.
				if (dp[curr][j] != INF) {
					t_maxi = max(t_maxi, dp[curr][j]);
				}
			}
			
			// t_maxi 는 현재 노드이 가지는 가장 큰 값이다. 이 비용이 현재 그룹의 최솟값이라면 최솟값을 교체한다. 
			if (t_maxi < maxi) {
				maxi = t_maxi;
				idx = curr;
			}
		}

		// 현재 그룹의 최솟값 Index를 삽입한다. 
		answer.push_back(idx);
	}

	return;
}

void solve() {
	// 일단 각 점에서 각 점으로의 최단 거리를 구한다. 
	// 그러면 연결된 점은 INF가 아니겠지만 끊어진 점은 INF가 된다/
	floyd();
	//같은 구역 내에서 대표를 구한다.
	representation();
	cout << answer.size() << '\n';
	sort(answer.begin(), answer.end());
	for (auto i : answer) {
		cout << i << '\n';
	}
	return;
}

'알고리즘 > 백준' 카테고리의 다른 글

백준 17822 : 원판돌리기(java)  (0) 2020.09.01
백준 1275 커피숍2  (0) 2020.08.31
백준 11657  (0) 2020.08.30
백준 1865 웜홀  (0) 2020.08.30
백준 14725 개미굴  (0) 2020.08.30