AOJ 0520 - Lightest Mobile
再帰的に紐がつり合う最小の重さを求めていけばいいです.
考えはすぐ(2日目)浮かんだけど凡ミス.
今後,スコープとあとでつかう変数の値を変えていないか確認します.
#include<iostream> int gcd(int a, int b){ if(b == 0)return a; return gcd(b, a%b); } struct Pole{ int left, right; Pole *red, *blue, *rred, *rblue; }; // 中和をとった時の重さを返す int trace(Pole pole){ int red_w, blue_w; if(pole.red == nullptr && pole.blue == nullptr){ red_w = pole.right; blue_w = pole.left; }else if(pole.red != nullptr && pole.blue != nullptr){ red_w = trace(*pole.red); blue_w = trace(*pole.blue); int g = gcd(pole.left * red_w, pole.right * blue_w), _red_w = red_w; red_w = pole.right * blue_w / g * _red_w; blue_w = pole.left * _red_w / g * blue_w; }else{ if(pole.red == nullptr){ std::swap(pole.red, pole.blue); std::swap(pole.left, pole.right); } int _red_w = trace(*pole.red), g = gcd(pole.left * _red_w, pole.right); red_w = pole.right / g * _red_w; blue_w = pole.left * _red_w / g; } return red_w + blue_w; } int main(){ int n; while(std::cin >> n, n){ Pole ps[100]; for(int i=0;i<100;i++){ ps[i].red = nullptr; ps[i].blue = nullptr; ps[i].rred = nullptr; ps[i].rblue = nullptr; ps[i].left = 0; ps[i].right = 0; } for(int i=0;i<n;i++){ int p, q, r, b; std::cin >> p >> q >> r >> b; r--;b--; int g = gcd(p, q); ps[i].left = p / g; ps[i].right = q / g; if(r != -1){ ps[i].red = &ps[r]; ps[r].rred = &ps[i]; } if(b != -1){ ps[i].blue = &ps[b]; ps[b].rblue = &ps[i]; } } int parent = 0; { Pole *p = &ps[0]; while(p->rred != nullptr || p->rblue != nullptr){ if(p->rred != nullptr){ p = p->rred; }else{ p = p->rblue; } } parent = p - &ps[0]; } std::cout << trace(ps[parent]) << std::endl; } }