首先是稀疏图,不难想到dij+heap

观察题目可以知道,0<=k<=10;

所以比较裸的想法就是,d[i,j]表示已经免费了i条线路后到达j的最短路

容易得到

d[i,j]:=min(d[i,j],d[i-1,k]);

d[i,j]:=min(d[i,j],d[i,k]+w[k,j]);

然后在做dij在选择中间点的时候,我们穷举一下免费的线路数就可以了;

然后就要维护10个堆……

语言表述有点渣,具体还是看程序吧

  1 const inf=2000000007;
  2 type point=record
  3        num,dis:longint;
  4      end;
  5      node=record
  6        next,cost,point:longint;
  7      end;
  8 
  9 var edge:array[0..200010] of node;
 10     heap:array[0..11,0..10010] of point;
 11     d,where:array[0..11,0..10010] of longint;
 12     h:array[0..11] of longint;
 13     p:array[0..10010] of longint;
 14     len,x,y,z,i,j,n,m,u,k,s,t:longint;
 15 
 16 procedure swap(var a,b:point);
 17   var c:point;
 18   begin
 19     c:=a;
 20     a:=b;
 21     b:=c;
 22   end;
 23 
 24 function min(a,b:longint):longint;
 25   begin
 26     if a>b then exit(b) else exit(a);
 27   end;
 28 
 29 procedure add(x,y,z:longint);
 30   begin
 31     inc(len);
 32     edge[len].point:=y;
 33     edge[len].cost:=z;
 34     edge[len].next:=p[x];
 35     p[x]:=len;
 36   end;
 37 
 38 procedure sift(p,i:longint);
 39   var j,x,y:longint;
 40   begin
 41     j:=i shl 1;
 42     while j<=h[p] do
 43     begin
 44       if (j+1<=h[p]) and (heap[p,j].dis>heap[p,j+1].dis) then inc(j);
 45       if heap[p,i].dis>heap[p,j].dis then
 46       begin
 47         x:=heap[p,i].num;
 48         y:=heap[p,j].num;
 49         where[p,x]:=j;
 50         where[p,y]:=i;
 51         swap(heap[p,i],heap[p,j]);
 52         i:=j;
 53         j:=i shl 1;
 54       end
 55       else break;
 56     end;
 57   end;
 58 
 59 procedure up(p,i:longint);
 60   var j,x,y:longint;
 61   begin
 62     j:=i shr 1;
 63     while j>0 do
 64     begin
 65       if heap[p,i].dis<heap[p,j].dis then
 66       begin
 67         x:=heap[p,i].num;
 68         y:=heap[p,j].num;
 69         where[p,x]:=j;
 70         where[p,y]:=i;
 71         swap(heap[p,i],heap[p,j]);
 72         i:=j;
 73         j:=j shr 1;
 74       end
 75       else break;
 76     end;
 77   end;
 78 
 79 begin
 80   len:=-1;
 81   fillchar(p,sizeof(p),255);
 82   readln(n,m,k);
 83   readln(s,t);
 84   inc(s);  //点序号都+1,习惯一点
 85   inc(t);
 86   for i:=1 to m do
 87   begin
 88     readln(x,y,z);
 89     inc(x);
 90     inc(y);
 91     add(x,y,z);
 92     add(y,x,z);
 93   end;
 94   for i:=1 to n do
 95     if i<>s then
 96     begin
 97       for j:=0 to k do
 98         d[j,i]:=inf;
 99     end
100     else
101       for j:=0 to k do
102         d[j,i]:=0;
103   for i:=0 to k do
104   begin
105     for j:=1 to n do
106     begin
107       heap[i,j].num:=j;
108       heap[i,j].dis:=d[i,j];
109       where[i,j]:=j;
110     end;
111     h[i]:=n;
112   end;
113   for i:=0 to k do
114     up(i,s);  //起点不一定是0,要初始化堆,一开始这里被坑翻了
115   for u:=1 to n do
116   begin
117     for j:=k downto 0 do 
118     begin
119       x:=heap[j,1].num;
120       y:=heap[j,h[j]].num;  
121       if (h[j]=0) or (d[j,x]=inf) then continue;
122       where[j,y]:=1;  //dij+heap比较重要的细节
123       swap(heap[j,1],heap[j,h[j]]);
124       dec(h[j]); 
125       sift(j,1);  //出堆,调整堆
126       i:=p[x];
127       while i<>-1 do
128       begin
129         y:=edge[i].point;
130         if (j<>k) and (d[j+1,y]>d[j,x]) then   //两种情况
131         begin
132           d[j+1,y]:=d[j,x];
133           heap[j+1,where[j+1,y]].dis:=d[j+1,y];
134           up(j+1,where[j+1,y]);
135         end;
136         if (d[j,y]>d[j,x]+edge[i].cost) then
137         begin
138           d[j,y]:=d[j,x]+edge[i].cost;
139           heap[j,where[j,y]].dis:=d[j,y];
140           up(j,where[j,y]);
141         end;
142         i:=edge[i].next;
143       end;
144     end;
145   end;
146   writeln(d[k,t]); //肯定尽可能免费好啊
147 end.
View Code

 

posted on 2014-07-05 22:49  acphile  阅读(129)  评论(0编辑  收藏  举报