http://acm.pku.edu.cn/JudgeOnline/problem?id=1202
Пример решения на Pascal:
Код:
const
N_MAX = 300;
type
percent = record ready : boolean; dig_no : word; digits : array[1..N_MAX] of byte end;
var
n, k : word;
m : longint;
parent : array[1..N_MAX,1..2] of word;
rel : array[1..N_MAX,1..N_MAX] of percent;
anc : array[1..N_MAX,1..N_MAX] of boolean;
{ anc[a,b]: is b ancestor of a }
(* THE ARITHMETIC OF N_MAX-DIGIT NUMBERS *)
procedure percent_dump(var p : percent);
var
i : word;
begin
if p.digits[1] <> 0 then
begin
write(p.digits[1]);
write(p.digits[2])
end
else if p.digits[2] <> 0 then
write(p.digits[2]);
write(p.digits[3]);
if p.dig_no > 3 then
begin
write('.');
for i := 4 to p.dig_no do
write(p.digits[i])
end;
writeln('%');
end; { percent_dump }
procedure percent_init(var p : percent; val : byte);
begin
p.dig_no := 3;
p.digits[1] := val div 100;
p.digits[2] := (val mod 100) div 10;
p.digits[3] := val mod 10;
end; { percent_init }
procedure percent_average(var p1, p2, p3 : percent);
{ The only non-trivial operation we need: p3 := (p1 + p2) / 2 }
var
i, j : word;
sum : byte;
carry : byte;
dig_no : word;
begin
if p1.dig_no > p2.dig_no then
begin
dig_no := p1.dig_no;
for i := p2.dig_no+1 to dig_no do p2.digits[i] := 0
end
else
begin
dig_no := p2.dig_no;
for i := p1.dig_no+1 to dig_no do p1.digits[i] := 0
end;
carry := 0;
for i := 1 to dig_no do
begin
sum := p1.digits[i] + p2.digits[i];
p3.digits[i] := (sum div 2) + carry;
j := i;
while (p3.digits[j] > 9) do
begin
inc(p3.digits[j-1]);
dec(p3.digits[j],10);
dec(j)
end;
carry := (sum mod 2)*5;
end;
p3.dig_no := dig_no;
if carry > 0 then
begin
inc(p3.dig_no);
p3.digits[p3.dig_no] := carry
end;
while (p3.dig_no > 3) and (p3.digits[p3.dig_no] = 0) do
dec(p3.dig_no)
end; { percent_average }
procedure percent_copy(var p1, p2 : percent);
var
i : word;
begin
p2.ready := p1.ready;
p2.dig_no := p1.dig_no;
for i := 1 to p1.dig_no do
p2.digits[i] := p1.digits[i]
end; { percent_copy }
(* THE ANCESTOR GRAPH *)
procedure compute_anc(a,x : word);
{ Simple dfs }
var
i : word;
begin
if parent[x,1] = 0 then exit;
for i := 1 to 2 do
if not anc[a,parent[x,i]] then
begin
anc[a,parent[x,i]] := true;
compute_anc(a,parent[x,i])
end
end; { compute_anc }
(* THE IMPLEMENTATION OF THE RECURSIVE FORMULA *)
procedure compute_rel(a, b : word);
var
c : word;
begin
if rel[a,b].ready then exit;
if anc[b,a] then { we cannot go up from the ancestor }
begin c := a; a := b; b := c end;
if (a = b) then
percent_init(rel[a,b],100)
else if (parent[a,1] <> 0) then
begin
compute_rel(parent[a,1],b);
compute_rel(parent[a,2],b);
percent_average(rel[parent[a,1],b],
rel[parent[a,2],b],
rel[a,b])
end
else if (parent[b,1] <> 0) then
begin
compute_rel(a,parent[b,1]);
compute_rel(a,parent[b,2]);
percent_average(rel[a,parent[b,1]],
rel[a,parent[b,2]],
rel[a,b])
end
else
percent_init(rel[a,b],0);
rel[a,b].ready := true;
percent_copy(rel[a,b],rel[b,a]);
end; { compute_rel }
(* THE MAIN PROGRAM *)
var
a, b : word;
i : longint;
begin
readln(n,k);
for a := 1 to n do
begin
parent[a,1] := 0; parent[a,2] := 0;
end;
for i := 1 to k do
begin
read(a);
readln(parent[a,1],parent[a,2]);
end;
for a := 1 to n do
for b := 1 to n do
rel[a,b].ready := false;
for a := 1 to n do
for b := 1 to n do
anc[a,b] := false;
for a := 1 to n do
compute_anc(a,a);
readln(m);
for i := 1 to m do
begin
readln(a,b);
compute_rel(a,b);
percent_dump(rel[a,b]);
end;
end.