[이코테] 실전 문제

이들은 union-find, Kruskal의 알고리즘(최소 스패닝 트리) 및 위상 정렬과 관련된 문제입니다.
각 알고리즘의 설명 및 구현은 별도로 게시됩니다.

팀 빌딩

팀을 병합하고 같은 팀인지 확인하는 문제로 Union-Find 방법을 사용하여 풀어야 하는 문제였습니다.
오퍼레이션 0은 유니온을 만드는 오퍼레이션이었고, 오퍼레이션 1은 부모가 같은지 확인하는 오퍼레이션이었습니다.
각각에 대해 makeUnion 및 findParent 작업을 생성하여 문제를 해결했습니다.

int parent(100001) = { 0 };

int find_parent(int a, int b) { //항상 a<b 인 값이 들어온다
	if (parent(b) !
= b) { //한 집합 안에 있을수도 있음 parent(b) = find_parent(a, parent(b)); } return parent(b); } void make_union(int a,int b) { a = find_parent(parent(a), a); b = find_parent(parent(b), b); if (a < b) { parent(b) = a; } else parent(a) = b; } int main() { int N, M; int i; int oper, a, b; int compareP, p; scanf("%d %d", &N, &M); for (i = 0; i <= M; i++) { //처음에 parent를 자기 자신으로 초기화 parent(i) = i; } for (i = 0; i < M; i++) { scanf("%d %d %d", &oper, &a, &b); if (oper == 0) { make_union(a, b); } else if (oper == 1) { if (a < b) { p = find_parent(a, b); //b의 parent가 p compareP = a; } else { p = find_parent(b, a); //a의 parent가 p compareP = b; } if (p == compareP) printf("YES\n"); else printf("NO\n"); } } } /* 7 8 0 1 3 1 1 7 0 7 6 1 7 1 0 3 7 0 4 2 0 1 1 1 1 1 */


지구 계획

문제는 그래프의 최소 스패닝 트리를 구하고 최소 스패닝 트리를 구성하는 에지의 합(-최대 에지)을 찾는 것이었다.
그래프의 에지 정보를 입력하고 에지를 정렬한 후 Kruskal 알고리즘을 사용하여 최소 스패닝 트리를 구성하고 끝에 추가된 에지의 길이를 빼기만 하면 답을 얻을 수 있습니다.

vector<tuple<int, int, int>> edge; //w, a,b -> 간선을 가중치 기준으로 정렬해야 하기 때문
//최소신장트리의 간선이 가중치 순서대로 들어 있고, 가중치를 저장함 
//여기에 저장되어 있는 간선만 남기고 나머지 간선은 필요 없음 + treeWeight(N) 또한 필요 없음(그래프를 2개로 나눌 때 가장 비싼 간선을 버리면 됨)
int parent(100001); //각 정점의 부모

void initParent(int N); //parent를 자기 자신으로 초기화
bool isUnion(int a, int b); //a와 b가 같은 그룹인지 확인
void makeUnion(int a, int b); //a와 b를 합치기
int findParent(int a); //a의 부모 찾기
int minTreeSum = 0; //최소신장 트리의 가중치 합 (마지막 가중치 제외)
int lastWeight; //마지막 가중치

void kruskal(int N, int M); //최소 신장 트리 만들기

int main() {

	int N, M;
	int i;
	int A, B, C;
	int originSum=0; //맨 처음 그래프의 모든 간선의 가중치 합

	scanf("%d %d", &N, &M);

	for (i = 0; i < M; i++) {
		scanf("%d %d %d", &A, &B, &C);				
		edge.push_back({ C,A,B });
		originSum += C;
	}
	
	kruskal(N, M);

	printf("%d", minTreeSum - lastWeight);

}

void initParent(int N) {
	int i;
	for (i = 1; i <= N; i++) {
		parent(i) = i;
	}
}

bool isUnion(int a, int b) {
	int pa, pb;

	pa = findParent(a);
	pb = findParent(b);
	if (pa == pb) return true;
	else return false;
}

void makeUnion(int a, int b) {
	a = findParent(a);
	b = findParent(b);

	if (a < b) {
		parent(b) = a;
	}
	else parent(a) = b;
}

int findParent(int a) {
	if (parent(a) !
= a) { //상위 조상이 존재함 parent(a) = findParent(parent(a)); } return parent(a); } void kruskal(int N, int M) { //M개의 간선을 하나씩 조사하기 start와 end가 union인지, 아니면 union 만들고 tree에 넣기 int i; int a, b, w; //간선 sort 해주기 sort(edge.begin(), edge.end()); //parent 값 초기화 initParent(N); for (i = 0; i < M; i++) { w = get<0>(edge(i)); a = get<1>(edge(i)); b = get<2>(edge(i)); if (!
isUnion(a,b)) { //union이 아니면 makeUnion(a, b); //그룹 만들기 minTreeSum += w; lastWeight = w; //printf("make i: %d a: %d b: %d w: %d\n",i,a,b,w); } } } /* 7 12 1 2 3 1 3 2 3 2 1 2 5 2 3 4 4 7 3 6 5 1 5 1 6 2 6 4 1 6 5 3 4 5 3 6 7 4


과정

대표적인 위상 정렬 문제로 각 노드의 시간을 출력하는 문제이다.

진입도가 가장 낮은 노드를 순서대로 검사하여 dist 값을 구합니다.

#define MAX_INT 
using namespace std;

vector<int> g(501); //연결된 노드
int time(501) = { 0 };
int in(501) = { 0 }; //각 노드의 진입차수
int dist(501); //결과
int N;

void topology() {
	queue<int> q; //진입차수 가장 낮은 노드
	int i;
	int nowNode;
	int nextNode;
	
	for (i = 1; i <= N; i++) { //처음에 진입차수 0인 노드 넣기
		if (in(i) == 0) {
			q.push(i);
		}
		dist(i) = time(i);
	}

	while (!
q.empty()) { nowNode = q.front(); q.pop(); for (i = 0; i < g(nowNode).size(); i++) { nextNode = g(nowNode)(i); //dist 정정 dist(nextNode) = max(dist(nextNode), dist(nowNode) + time(nextNode)); in(nextNode)--; if (in(nextNode) == 0) { //진입차수 0 되면 q에 push q.push(nextNode); } } } } int main() { int t, num; int i; scanf("%d", &N); for (i = 1; i <= N; i++) { scanf("%d", &t); while (1) { scanf("%d", &num); if (num == -1) break; g(num).push_back(i); in(i)++; } time(i) = t; } topology(); for (i = 1; i <= N; i++) { printf("%d\n", dist(i)); } } /* 5 10 -1 10 1 -1 4 1 -1 4 3 1 -1 3 3 -1 */

http://www.yes24.com/product/goods/91433923