http://acm.pku.edu.cn/JudgeOnline/problem?id=1206
Код:
program PKU1026;
{$i-, s-, q-, r-}
const
inf = '';
ouf = '';
maxn = 31000;
maxm = maxn * 10;
none = 1000000000;
type integer = longint;
var g, q, low, dis, rank, mark, time, dist: array[1 .. maxn] of integer;
tow, next, cost: array[1 .. maxm] of integer;
buf: array[0 .. 1 shl 16] of byte;
n, m, ans, tot: integer;
function min(i, j: integer): integer;
begin
if i < j then min := i else min := j;
end;
procedure insert(u, v, t: integer);
begin
tot := tot + 1;
next[tot] := g[u]; tow[tot] := v;
cost[tot] := t; g[u] := tot;
end;
procedure prepare;
var i, u, v, t: integer;
begin
fillchar(g, sizeof(g), 0);
read(n, m); tot := 0;
for i := 1 to n do read(rank[i]);
for i := 1 to m do begin
read(u, v, t);
insert(u, v, t);
insert(v, u, t);
end;
end;
procedure bfs(k: integer);
var open, closed: integer;
u, v, t, tmp: integer;
begin
ans := ans + 1;
open := 0; closed := 1;
q[1] := k; dis[k] := 0;
time[k] := k; dist[k] := 0;
mark[k] := k;
while open <> closed do begin
open := open + 1;
if open > maxn then open := 1;
u := q[open]; mark[u] := 0;
tmp := g[u];
while tmp <> 0 do begin
v := tow[tmp]; t := dis[u] + cost[tmp];
if t < low[v] then
if (time[v] <> k) or (t < dis[v]) then begin
dis[v] := t; dist[v] := min(dist[v], dis[v]);
if time[v] <> k then begin
ans := ans + 1;
time[v] := k;
end;
if mark[v] <> k then begin
mark[v] := k;
closed := closed + 1; if closed > maxn then closed := 1;
q[closed] := v;
end;
end;
tmp := next[tmp];
end;
end;
end;
procedure main;
var i, high: integer;
begin
ans := 0;
for i := 1 to n do low[i] := none;
for high := 10 downto 1 do begin
fillchar(time, sizeof(time), 0);
fillchar(mark, sizeof(mark), 0);
for i := 1 to n do dist[i] := none;
for i := 1 to n do if rank[i] = high then bfs(i);
for i := 1 to n do low[i] := min(low[i], dist[i]);
end;
writeln(ans);
end;
begin
assign(input, inf); assign(output, ouf);
settextbuf(input, buf);
reset(input); rewrite(output);
prepare;
main;
close(Input); close(output);
end.