AIZU ONLINE JUDGE

AOJ ALDS1 7_A(Rooted Trees)を解く

AOJ_ALDS1_7_A

Aizu Online Judge(AOJ)が提供している「アルゴリズムとデータ構造入門」(ALDS1)の7_A問題をC++で解いてみました。

ALDS1では、「アルゴリズムとデータ構造の基礎を体得します。」とあります。トピック#7「木構造」では、根付き木、二分木について紹介します。

問題(7_A: Rooted Trees)

問題はリンク先をご覧ください。

AOJ ALDS1 7_A問題: Rooted Trees

根付き木の構造について学びます。

木構造について(用語の整理)

入力例1の木構造を図示すると以下となります。

木構造の用語を整理します。図を用いて例示します。

  • 根:その親がないグラフの頂点です。頂点0が根となります。
  • 子:頂点0の子は、頂点1、4、10となります。
  • 親:頂点1の親は頂点0、頂点8の親は頂点7となります。
  • 葉:子がない頂点です。頂点2、3、5、6、8、9、11、12が葉になります。
  • 内部節点:根でも葉でもない頂点です。頂点1、4、7、10が内部節点となります。

C++ プログラム例(ALDS1 7_A)

グラフとして処理します。

  • 子として出てこない頂点が根になります。これはsetコンテナを用いて求めます。
  • DFSを用いて、親(配列 parent)と深さ(配列 depth)を求めます。木を前提としているため、関数 dfs の実装は簡単になっています。
  • 問題で示された出力をします。
    • 入力例2の出力をみると、子の頂点はソートする必要はないようです。

以下が、C++プログラムとなります。

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;

vector<vector<int>> G;
vector<int> parent;
vector<int> depth;

void dfs(int v, int p, int d)
{
	parent[v] = p;
	depth[v] = d;
	for (auto next_v : G[v]) {
		dfs(next_v, v, d + 1);
	}
}

int main()
{
	int n;
	cin >> n;
	G.resize(n);
	set<int> root;
	for (int i = 0; i < n; ++i) {
		root.insert(i);
	}
	for (int i = 0; i < n; ++i) {
		int id;
		int k;
		cin >> id >> k;
		for (int j = 0; j < k; ++j) {
			int c;
			cin >> c;
			G[id].push_back(c);
			root.erase(c);
		}
	}

	parent.resize(n);
	depth.resize(n);
	int r = *(root.begin());
	dfs(r, -1, 0);

	for (int i = 0; i < n; ++i) {
		cout << "node " << i << ": ";
		cout << "parent = " << parent[i] << ", ";
		cout << "depth = " << depth[i] << ", ";
		if (i == r) {
			cout << "root, ";
		} else if (G[i].size() > 0) {
			cout << "internal node, ";
		} else {
			cout << "leaf, ";
		}
		cout << "[";
		for (int j = 0; j < G[i].size(); ++j) {
			if (j != 0) {
				cout << ", ";
			}
			cout << G[i][j];
		}
		cout << "]" << endl;
	}

	return 0;
}

上記プログラムは、AOJ で「AC(Accepted=正解)」と判定されました。

最後に

トピック#7 では、木構造について学びます。

引き続き、ALDS1 の問題を紹介していきます。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA