poj3613

来源:互联网 发布:纸黄金分析软件 编辑:程序博客网 时间:2024/05/01 03:27

【题意】

t条路,问从s到e经过n条边的最小路程

【输入】

第一行n、t、s、e

接下来t行为边的长度、边的两个端点编号

【输出】

从s到e经过n条边最小路程


做flyod,本身需要枚举n次,基于快速幂思想加速

需要注意的是评测网站和noi的pascal内核都为2.0.4

递归很容易溢出


program poj3613;type  arr=array [0..201,0..201] of int64;var  n,t,i,j,k,s,e,tot,all:longint;  dl,map,u,v,c:array [0..10001] of longint;  dis,root,temp,p:arr;function min (a,b:int64):int64;begin  if a<b then exit(a)         else exit(b);end;procedure swap (var a,b:longint);var  i:longint;begin  i:=a;  a:=b;  b:=i;end;procedure qsort (s,e:longint);var  i,j,k:longint;begin  if s>=e then exit;  i:=s;  j:=e;  k:=dl[(s+e) div 2];  while i<=j do    begin      while dl[i]<k do inc(i);      while dl[j]>k do dec(j);      if i>j then break;      swap(dl[i],dl[j]);      inc(i);      dec(j);    end;  qsort(s,j);  qsort(i,e);end;begin  fillchar(root,sizeof(root),63);  read(n,t,s,e);  tot:=0;  for i:=1 to t do    begin      read(c[i],u[i],v[i]);      inc(tot);      dl[tot]:=u[i];      inc(tot);      dl[tot]:=v[i];    end;  qsort(1,tot);  all:=1;  k:=1;  for i:=1 to tot do    begin      if dl[i]<>dl[k] then        begin          k:=i;          inc(all);        end;      map[dl[i]]:=all;    end;  for i:=1 to t do    begin      root[map[u[i]],map[v[i]]]:=min(root[map[u[i]],map[v[i]]],c[i]);      root[map[v[i]],map[u[i]]]:=min(root[map[v[i]],map[u[i]]],c[i]);    end;  tot:=1;  while n>0 do    begin      dl[tot]:=n;      n:=n div 2;      inc(tot);    end;  dec(tot);  dis:=root;  dec(tot);  while tot>0 do    begin      p:=dis;      fillchar(temp,sizeof(temp),63);      for i:=1 to all do        for j:=1 to all do          for k:=1 to all do            temp[i,k]:=min(temp[i,k],p[i,j]+p[j,k]);      fillchar(dis,sizeof(dis),63);      if dl[tot] and 1 = 1 then        for i:=1 to all do          for j:=1 to all do            for k:=1 to all do              dis[i,k]:=min(dis[i,k],temp[i,j]+root[j,k])                           else        dis:=temp;      dec(tot);    end;  s:=map[s];  e:=map[e];  writeln(dis[s,e]);end.