グラフ・DFSメニュー【全域木の判定・全域木の出力 1〜3・次数が 2 以下の全域木の出力】
【全域木の判定】コード
reader.on('close', () => {
const dfs = (now, seen) => { // (現在地, 訪問済)
const nexts = list[now]; // 隣接している頂点
for (const next of nexts) { // 隣接している各頂点が…
if (!seen.includes(next)) { // 未訪問なら…
seen.push(next); // 訪問済にする
dfs(next, seen); // next に移動
}
}
return seen.length; // seen の要素数を返す
};
const n = Number(lines.shift());
const list = new Array(n).fill().map(e => []);
let edge_num = 0; // 枝の数
for (let i = 0; i < n; i++) {
const v = Number(lines.shift()); // 隣接している頂点の数
edge_num += v;
const a = lines.shift().split(' ').map(e => e - 1);
list[i] = a;
}
if (n - edge_num / 2 === 1) { // 頂点数 - 枝の数 / 2 が 1 なら…
console.log(dfs(0, [0]) === n ? 'Yes' : 'No');
} else {
console.log('No');
}
});
全域木…全域部分グラフ(そのグラフの全頂点を含む部分グラフ)のうち、木(連結で閉路を持たないグラフ)であるものをいう。
(ウィキペディア)
【全域木の出力】コード
reader.on('close', () => {
const dfs = (now, seen, edges) => { // (現在地, 訪問済, 枝)
const nexts = list[now];
for (const next of nexts) {
if (!seen.includes(next)) {
seen.push(next);
edges.push([now, next]); // 現在地 と 次の頂点のペアを保存
dfs(next, seen, edges);
}
}
return edges;
};
const n = Number(lines.shift());
const list = new Array(n).fill().map(e => []);
for (let i = 0; i < n; i++) {
const v = Number(lines.shift());
const a = lines.shift().split(' ').map(e => e - 1);
list[i] = a;
}
const Edges = dfs(0, [0], []);
Edges.forEach(edge => {
console.log(...edge.map(e => e + 1));
});
});
next が 未訪問なら[now, next ]を edges に保存。
【全域木の出力 2】コード
reader.on('close', () => {
const dfs = (now, seen, edges = []) => {
const nexts = list[now];
for (const next of nexts) {
if (!seen.includes(next)) {
seen.push(next);
edges.push([now, next]);
dfs(next, seen, edges);
}
}
return edges;
};
const n = Number(lines.shift());
const list = new Array(n).fill().map(e => []);
for (let i = 0; i < n; i++) {
const v = Number(lines.shift());
const a = lines.shift().split(' ').map(e => e - 1);
list[i] = a;
}
const k = Number(lines.shift());
for (let i = 0; i < k; i++) {
const [e, d] = lines.shift().split(' ').map(e => e - 1);
const e_d = list[e].indexOf(d);
const d_e = list[d].indexOf(e);
list[e].splice(e_d, 1);
list[d].splice(d_e, 1);
}
const Edges = dfs(0, [0]);
if (Edges.length === n - 1) {
Edges.forEach(edge => {
console.log(...edge.map(e => e + 1));
});
} else {
console.log(-1);
}
});
E に含まれる枝を予め list から削除してから dfs() を呼び出しました。
【全域木の出力 3 】コード
reader.on('close', () => {
const dfs = (now, seen) => {
const nexts = list[now];
for (const next of nexts) {
if (!seen.includes(next)) {
edges.push([now, next]);
seen.push(next);
dfs(next, seen);
}
}
};
const n = Number(lines.shift());
const k = Number(lines.shift());
const S = lines.shift().split(' ').map(e => e - 1);
const list = new Array(n).fill().map(e => []);
for (let i = 0; i < n; i++) {
const v = Number(lines.shift());
const a = lines.shift().split(' ').map(e => e - 1);
list[i] = a;
}
const node = n - k - 1;
const edges = [];
dfs(0,[0,...S]);
if (edges.length === node) {
for (const edge of edges) {
console.log(...edge.map(e => e + 1));
}
}else {
console.log(-1);
}
});
S に含まれる頂点は予め通過済みとしてから dfs() を呼び出しました。
【次数が 2 以下の全域木の出力】コード 92点
reader.on('close', () => {
const dfs = (now, seen) => {
const nexts = list[now];
for (const next of nexts) {
if (!seen.includes(next)) {
edges.push([now, next]);
return dfs(next, [...seen, next]);
}
}
};
const n = Number(lines.shift());
const list = new Array(n).fill().map(e => []);
const start = [];
for (let i = 0; i < n; i++) {
const v = Number(lines.shift());
if (v === 1) {
start.push(i);
}
const a = lines.shift().split(' ').map(e => e - 1);
list[i] = a;
}
const edges = [];
if (start.length > 0 && start.length < 3) {
dfs(start[0], [start[0]]);
} else {
for (let i = 0; i < n; i++) {
dfs(i, [i]);
if (edges.length === n - 1) {
break;
} else {
edges.length = 0;
}
}
}
if (edges.length === n - 1) {
for(const edge of edges){
console.log(...edge.map(e =>e+1));
}
} else {
console.log(-1);
}
});
100点にできなかった。(´·ω·`)
コメント