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.