pku3662 Telephone Lines

给一个n个点,m条边的图,每条边上有费用,求1到n的路径中最长边最小值,其中可以选择k条边不计费用

最大最小问题,看见就二分答案

布尔数组 d[i,j]表示在第i点,选择j条边免费,且其余边中最大值小于二分值,的状态是否可以达到

用SPFA扩展即可,最后在d[i,0..k]中只要有一个是TRUE,该二分值就成立

由我的程序,可以延伸出两种优化算法

1.可以把d[i,j]表示到i点用了j条免费边后起点到当前点的最大值,一边SPFA之后,d[n,0..k]中的最小值就是答案。

2.二分答案,d[i]记录超过答案的边数,如果最终d[n]<=k,则合法

View Code
  1 program pku3662(input,output);
2 type
3 node = ^link;
4 link = record
5 goal : longint;
6 w : int64;
7 next : node;
8 end;
9 node2 = record
10 now : longint;
11 suml : int64;
12 end;
13 var
14 l : array[0..1001] of node;
15 d : array[0..1001,0..1001] of boolean;
16 q : array[0..25001] of node2;
17 v : array[0..1001,0..1001] of boolean;
18 n,m,maxk : longint;
19 procedure add(xx,yy: longint; ww:int64 );
20 var
21 t : node;
22 begin
23 new(t);
24 t^.w:=ww;
25 t^.goal:=yy;
26 t^.next:=l[xx];
27 l[xx]:=t;
28 end; { add }
29 procedure init;
30 var
31 i,xxx,yyy,www : longint;
32 begin
33 readln(n,m,maxk);
34 for i:=1 to n do
35 l[i]:=nil;
36 for i:=1 to m do
37 begin
38 read(xxx,yyy,www);
39 add(xxx,yyy,www);
40 add(yyy,xxx,www);
41 end;
42 end; { init }
43 function spfa(kill : int64 ):boolean;
44 var
45 head,tail,i : longint;
46 t : node;
47 begin
48 fillchar(d,sizeof(d),false);
49 fillchar(v,sizeof(v),false);
50 head:=0;
51 tail:=1;
52 q[1].now:=1;
53 q[1].suml:=0;
54 d[1,0]:=true;
55 v[1,0]:=true;
56 while head<tail do
57 begin
58 inc(head);
59 v[q[head].now,q[head].suml]:=false;
60 t:=l[q[head].now];
61 while t<>nil do
62 begin
63 if t^.w>kill then
64 begin
65 if q[head].suml<>maxk then
66 if not d[t^.goal,q[head].suml+1] then
67 begin
68 d[t^.goal,q[head].suml+1]:=true;
69 if not v[t^.goal,q[head].suml+1] then
70 begin
71 inc(tail);
72 q[tail].now:=t^.goal;
73 q[tail].suml:=q[head].suml+1;
74 v[t^.goal,q[head].suml+1]:=true;
75 end;
76 end;
77 end
78 else
79 begin
80 if not d[t^.goal,q[head].suml] then
81 begin
82 d[t^.goal,q[head].suml]:=true;
83 if not v[t^.goal,q[head].suml] then
84 begin
85 inc(tail);
86 q[tail].now:=t^.goal;
87 q[tail].suml:=q[head].suml;
88 v[t^.goal,q[head].suml]:=true;
89 end;
90 end;
91 end;
92 t:=t^.next;
93 end;
94 end;
95 for i:=0 to maxk do
96 if d[n,i] then
97 exit(true);
98 exit(false);
99 end; { spfa }
100 procedure main;
101 var
102 left,right,mid : longint;
103 begin
104 if not spfa(maxlongint>>4) then
105 begin
106 writeln(-1);
107 exit;
108 end;
109 if spfa(0) then
110 begin
111 writeln(0);
112 exit;
113 end;
114 left:=0;
115 right:=2000000;
116 while left+1<right do
117 begin
118 mid:=(left+right)>>1;
119 if spfa(mid) then
120 right:=mid
121 else
122 left:=mid;
123 end;
124 writeln(right);
125 end; { main }
126 begin
127 assign(input,'phoneline.in');reset(input);
128 assign(output,'phoneline.out');rewrite(output);
129 init;
130 main;
131 close(input);
132 close(output);
133 end.



posted @ 2012-02-28 15:41  Codinginging  阅读(204)  评论(0编辑  收藏  举报