倍增好题,f[p,i,j]表示i到j经过了2^p条边走过的最短路径
显然f[p+1]可以由f[p]转移来
然后对n二进制拆分累加即可

 1 const inf=9999999999;
 2 
 3 var map,pm:array[0..110,0..110] of int64;
 4     f,pf:array[0..110] of int64;
 5     v:array[0..1010] of longint;
 6     j,z,x,y,s,t,n,m,e,i:longint;
 7 
 8 function min(a,b:int64):int64;
 9   begin
10     if a>b then exit(b) else exit(a);
11   end;
12 
13 function get(x:longint):longint;
14   begin
15     if v[x]=0 then
16     begin
17       inc(t);
18       v[x]:=t;
19     end;
20     exit(v[x]);
21   end;
22 
23 procedure time1;
24   var i,j:longint;
25   begin
26     pf:=f;
27     for i:=1 to t do
28     begin
29       f[i]:=inf;
30       for j:=1 to t do
31         f[i]:=min(f[i],pf[j]+map[j,i]);
32     end;
33   end;
34 
35 procedure time2;
36   var i,j,k:longint;
37   begin
38     pm:=map;
39     for i:=1 to t do
40       for j:=1 to t do
41       begin
42         map[i,j]:=inf;
43         for k:=1 to t do
44           map[i,j]:=min(map[i,j],pm[i,k]+pm[k,j]);
45       end;
46   end;
47 
48 procedure work(x:longint);
49   begin
50     while x>0 do
51     begin
52       if x mod 2=1 then time1;
53       x:=x shr 1;
54       if x<>0 then time2;
55     end;
56   end;
57 
58 begin
59   readln(n,m,s,e);
60   for i:=1 to 100 do
61     for j:=1 to 100 do
62       map[i,j]:=inf;
63   for i:=1 to m do
64   begin
65     readln(z,x,y);
66     x:=get(x);
67     y:=get(y);
68     map[x,y]:=z;
69     map[y,x]:=z;
70   end;
71   s:=get(s);
72   e:=get(e);
73   for i:=1 to t do
74     f[i]:=inf;
75   f[s]:=0;
76   work(n);
77   writeln(f[e]);
78 end.
View Code

 

posted on 2014-12-25 21:12  acphile  阅读(199)  评论(0编辑  收藏  举报