pku3311 Hie with the Pie
给定一个n个顶点的完全有向图,求从0点出发遍历所有点之后回到0点的最小路径长度。
网上很多人用floyd之后再dp的算法,看起来没什么意思,这种题正是二维SPFA的用武之地,
d[now,state]表示到now点,状态为state的最短路径,其中state为把遍历情况压缩为二进制数的十进制值,SPFA之后输出d[0,(1<<(n+1))-1]即可,
由于习惯问题,代码中我把所有的编号都+1了。
View Code
1 program pku3311(input,output);
2 type
3 node = record
4 now,state : longint;
5 end;
6 var
7 q : array[0..50000] of node;
8 f : array[0..12,0..12] of longint;
9 d : array[0..12,0..3000] of longint;
10 v : array[0..12,0..3000] of boolean;
11 n : longint;
12 procedure init;
13 var
14 i,j,k : longint;
15 begin
16 inc(n);
17 for i:=1 to n do
18 begin
19 for j:=1 to n do
20 read(f[i,j]);
21 readln;
22 end;
23 end; { init }
24 procedure spfa();
25 var
26 head,tail,i : longint;
27 new : node;
28 begin
29 q[1].now:=1;
30 q[1].state:=1;
31 fillchar(v,sizeof(v),false);
32 fillchar(d,sizeof(d),63);
33 d[1,1]:=0;
34 v[1,1]:=true;
35 head:=0;
36 tail:=1;
37 while head<tail do
38 begin
39 inc(head);
40 v[q[head].now,q[head].state]:=false;
41 for i:=1 to n do
42 if f[q[head].now,i]>0 then
43 begin
44 new.now:=i;
45 new.state:=q[head].state or (1<<(i-1));
46 if d[q[head].now,q[head].state]+f[q[head].now,i]<d[new.now,new.state] then
47 begin
48 d[new.now,new.state]:=d[q[head].now,q[head].state]+f[q[head].now,i];
49 if not v[new.now,new.state] then
50 begin
51 inc(tail);
52 q[tail]:=new;
53 v[new.now,new.state]:=true;
54 end;
55 end;
56 end;
57 end;
58 end; { spfa }
59 procedure print;
60 begin
61 writeln(d[1,(1<<n)-1]);
62 end; { print }
63 begin
64 readln(n);
65 while n<>0 do
66 begin
67 init;
68 spfa;
69 print;
70 readln(n);
71 end;
72 end.