木のメニュー 【距離が X の頂点・二頂点間の経路・木の同型判定・根付き木の根の変更】
【距離が X の頂点】コード 1/2
reader.on('close', () => {
const adjacency_List = (a, b) => {
List[a].push(b);
List[b].push(a);
};
const [N, A, X] = lines.shift().split(' ').map(Number);
const range = new Array(N).fill(-1); // 根 からの距離
const Q = [A - 1]; // 幅優先探索のためのキュー Q (根から探索開始)
range[A - 1] = 0; // 根 は 距離 0
const List = []; // 隣接リスト
for (let i = 0; i < N; i++) {
List.push([]);
}
for (let i = 0; i < N - 1; i++) {
const [A, B] = lines.shift().split(' ').map(e => e - 1);
adjacency_List(A, B);
}
while (Q.length) { // Q が空になるまで繰り返し
const now = Q.shift(); // Q の先頭の値を取り出して now とする
const nexts = List[now]; // A に隣接した頂点
nexts.forEach(next => { // A に隣接した頂点のうち…
if (range[next] === -1) { // 未訪問(距離が確定していない)頂点の…
range[next] = range[now] + 1; // 距離を range[now] + 1 として…
Q.push(next); // その頂点を Q に追加
}
});
}
range.forEach((value, index) => {
if (value === X) { // value が X なら…
console.log(index + 1); // index + 1 を出力
}
});
});
upしました。
【距離が X の頂点】コード 2/2
reader.on('close', () => {
const adjacency_List = (a, b) => {
List[a].push(b);
List[b].push(a);
};
const bfs = (q, range) => { // 幅優先探索
if (!q.length) { // q が空になれば…
return range; // 根からの距離を返す
}
const now = q.shift(); // q の先頭の値を取り出して now とする
const next = List[now];
for (const node of next) { // now に隣接した頂点のうち…
if (range[node] === -1) { // 未訪問(距離が確定していない)頂点の…
range[node] = range[now] + 1; // 距離を range[now] + 1 として…
q.push(node); // その頂点を q に追加
}
}
return bfs(q, range); // bfs(q, range) を呼び出す
};
const [N, A, X] = lines.shift().split(' ').map(Number);
const Range = new Array(N).fill(-1); // 根 からの距離
const Q = [A - 1]; // 幅優先探索のためのキュー Q(根から探索開始)
Range[A - 1] = 0; // 根 は 距離 0
const List = [];
for (let i = 0; i < N; i++) {
List.push([]);
}
for (let i = 0; i < N - 1; i++) {
const [A, B] = lines.shift().split(' ').map(e => e - 1);
adjacency_List(A, B);
}
bfs(Q, Range);
Range.forEach((value, index) => {
if (value === X) {
console.log(index + 1);
}
});
});
upしました。
【二頂点間の経路】コード 1/2(幅優先順位探索)
reader.on('close', () => {
const adjacency_List = (a, b) => {
List[a].push(b);
List[b].push(a);
};
const [N, A, B] = lines.shift().split(' ').map(Number);
const List = [];
for (let i = 0; i < N; i++) {
List.push([]);
}
for (let i = 0; i < N - 1; i++) {
const [A, B] = lines.shift().split(' ').map(e => e - 1);
adjacency_List(A, B);
}
const Q = [A - 1]; // 幅優先探索のためのキュー Q(根から探索開始)
const stamp = new Array(N).fill(-1);
stamp[A - 1] = 'start';
while (Q.length) { // Q が空になるまで繰り返し
const now = Q.shift(); // Q の先頭の値を取り出して now とする
const next = List[now]; // now に隣接した頂点
for (const point of next) { // now に隣接した頂点のうち…
if (stamp[point] === -1) { // 未訪問の頂点を…
Q.push(point); // Q に追加
stamp[point] = now; // point に隣接している根に近い頂点を記録
}
}
}
const route = [B - 1]; // 経路(遡る)
let re_moved = B - 1; // 経路を遡った地点
while (stamp[re_moved] !== 'start') { // スタートにたどり着くまで繰り返し
re_moved = stamp[re_moved]; // 経路を遡った地点は re_moved に隣接している根に近い頂点
route.unshift(re_moved); // route の先頭に re_moved を追加
}
route.forEach(value => {
console.log(value + 1);
});
});
upしました。
【二頂点間の経路】コード 2/2(深さ優先順位探索)
reader.on('close', () => {
const dfs = (now, prev, route) => {
visited[now] = true; // now を訪問済みにする
for (const next of List[now]) { // 次の訪問先の候補が…
if (next === prev || visited[next]) { // 直前に訪問した頂点または訪問済みの頂点なら…
continue; // スキップ
}
visited[next] = true; // next を訪問済みにする
route.push(next + 1); // route に next 保存
if (next + 1 === B) { // next が B (ゴール) なら…
for (const i of route) {
console.log(i); // route の要素を出力
}
return;
}
dfs(next, now, route);
route.pop();
visited[next] = false;
}
};
const [N, A, B] = lines.shift().split(' ').map(Number);
const adjacency_List = (a, b) => {
List[a].push(b);
List[b].push(a);
};
const List = [];
for (let i = 0; i < N; i++) {
List.push([]);
}
for (let i = 0; i < N - 1; i++) {
const [A, B] = lines.shift().split(' ').map(e => e - 1);
adjacency_List(A, B);
}
const visited = new Array(N).fill(false);
dfs(A - 1, -1, [A]);
});
upしました。
【木の直径】コード
reader.on('close', () => {
const bfs = (q, range) => {
if (!q.length) {
return range;
}
const now = q.shift();
const next = List[now];
for (const node of next) { // A に隣接した頂点のうち…
if (range[node] === -1) {
range[node] = range[now] + 1;
q.push(node); // その頂点を Q に追加
}
}
return bfs(q, range);
};
const adjacency_List = (a, b) => {
List[a].push(b);
List[b].push(a);
};
const N = Number(lines.shift());
const Range = new Array(N).fill(-1); // 根 からの距離
const Q = [N - 1]; // 幅優先探索のためのキュー Q(根から探索開始)
Range[N - 1] = 0; // 根 は 距離 0
const List = [];
for (let i = 0; i < N; i++) {
List.push([]);
}
for (let i = 0; i < N - 1; i++) {
const [A, B] = lines.shift().split(' ').map(e => e - 1);
adjacency_List(A, B);
}
bfs([N - 1], Range);
const X = Range.indexOf(Math.max(...Range));
const RangeX = new Array(N).fill(-1); // 根 からの距離
RangeX[X] = 0; // 根 は 距離 0
bfs([X], RangeX);
console.log(Math.max(...RangeX));
});
upしました。
【木の同型判定】コード
reader.on('close', () => {
const N1 = Number(lines[0]);
const N2 = Number(lines[N1]);
let same = true;
if (N1 !== N2) {
same = false;
} else {
const N = N1;
const List1 = [];
const List2 = [];
for (let i = 0; i < N; i++) {
List1.push([]);
List2.push([]);
}
for (let i = 1; i < N; i++) {
const [A1, B1] = lines[i].split(' ').map(e => e - 1);
const [A2, B2] = lines[i + N].split(' ').map(e => e - 1);
List1[A1].push(B1);
List1[B1].push(A1);
List2[A2].push(B2);
List2[B2].push(A2);
}
const L1 = [];
const L2 = [];
for (let i = 0; i < N; i++) {
L1.push(List1[i].length);
L2.push(List2[i].length);
}
const L1_sort = L1.sort((s, b) => s - b);
const L2_sort = L2.sort((s, b) => s - b);
for (let i = 0; i < N; i++) {
if (L1_sort[i] !== L2_sort[i]) {
same = false;
break;
}
}
}
console.log(same ? 'YES' : 'NO');
});
upしました。
【根付き木の根の変更】コード
reader.on('close', () => {
const adjacency_list = (start, end, list, a, b) => {
for (let i = start; i <= end; i++) {
list.push([]);
}
for (let i = start; i < end; i++) {
[a, b] = lines.shift().split(' ').map(e => e - 1);
list[a].push(b);
list[b].push(a);
}
return list;
};
const bfs = (list, a, level, Q) => {
level[a] = 0;
while (Q.length) { // Q が空になるまで繰り返し
a = Q.shift(); // Q の先頭の値を取り出して a とする
const nexts = list[a]; // a に隣接した頂点
for (const next of nexts) {
if (level[next] === -1) {
level[next] = level[a] + 1;
Q.push(next);
}
}
}
return level;
};
const [N, R] = lines.shift().split(' ').map(Number);
const [K, r] = lines.splice(N-1,1)[0].split(' ').map(Number);
const list = adjacency_list(1, N, [], 0, 0);
const list_level_R = bfs(list, R - 1, new Array(N).fill(-1), [R - 1]);
const list_level_r = bfs(list, r - 1, new Array(N).fill(-1), [r - 1]);
list.forEach((value, index) => {
for (let i = 0; i < value.length; i++) {
const node = value[i];
if (list_level_r[node] < list_level_r[index]) {
value.splice(i, 1);
}
}
});
for (let i = N + 1; i <= N + K; i++) {
const node = lines.shift() - 1;
for (let i = 0; i < N; i++) {
if (list[i].includes(node)) {
console.log(i + 1);
break;
}
}
}
});
upしました。
コメント