现在的位置: 首页 > 综合 > 正文

poj3463

2018年04月26日 ⁄ 综合 ⁄ 共 3090字 ⁄ 字号 评论关闭

【题意】

给定一个有向加权图,求s到f的最短路径和比最短路径长1的路径数

【输入】

多组数据,第一行一个数字t表示有多少组数据

每组数据第一行两个数n、m表示点的个数和边的个数(n<=1000,m<=10000)

接下来m行每行三个整数a、b、l表示存在一条长度为l连接a、b的有向边

最后一行两个整数s、f

【输出】

对于每组数据输出一行,该行一个整数表示路径数

heap+dijkstra

如果用A*的话会超时,因为最终答案是10^8等级的

每个点维护两个值,最小值和次小值,再加上计数即可,代码略显臃肿

program poj3463;
var
  ans,tot,n,m,i,j,k,t,s,f,a,b,l:longint;
  root:array [0..10001] of longint;
  rank,count,dis:array [0..1,0..10001] of longint;
  next,point,cost:array [0..100001] of longint;
  heap,mode:array [0..20001] of longint;

procedure swap (var a,b:longint);
var
  i:longint;
begin
  i:=a;
  a:=b;
  b:=i;
end;

procedure connect (a,b,l:longint);
begin
  inc(tot);
  point[tot]:=b;
  cost[tot]:=l;
  next[tot]:=root[a];
  root[a]:=tot;
end;

procedure insert (o,now:longint);
var
  i:longint;
begin
  inc(tot);
  heap[tot]:=now;
  mode[tot]:=o;
  rank[o,now]:=tot;
  i:=tot;
  while (i>1)and(dis[mode[i div 2],heap[i div 2]]>dis[o,now]) do
    begin
      swap(rank[mode[i div 2],heap[i div 2]],rank[o,now]);
      swap(mode[i div 2],mode[i]);
      swap(heap[i div 2],heap[i]);
      i:=i div 2;
    end;
end;

procedure delete (o,now:longint);
var
  i:longint;
begin
  if rank[o,now]=0 then exit;
  if rank[o,now]=tot then
    begin
      heap[tot]:=0;
      mode[tot]:=0;
      rank[o,now]:=0;
      dec(tot);
      exit;
    end;
  i:=rank[o,now];
  swap(rank[o,now],rank[mode[tot],heap[tot]]);
  swap(heap[i],heap[tot]);
  swap(mode[i],mode[tot]);
  rank[o,now]:=0;
  heap[tot]:=0;
  mode[tot]:=0;
  dec(tot);
  if (i>1)and(dis[mode[i div 2],heap[i div 2]]>dis[mode[i],heap[i]]) then
    while (i>1)and(dis[mode[i div 2],heap[i div 2]]>dis[mode[i],heap[i]]) do
      begin
        swap(rank[mode[i div 2],heap[i div 2]],rank[mode[i],heap[i]]);
        swap(mode[i],mode[i div 2]);
        swap(heap[i],heap[i div 2]);
        i:=i div 2;
      end
                                                                     else
    while (dis[mode[i*2],heap[i*2]]<dis[mode[i],heap[i]])or
    (dis[mode[i*2+1],heap[i*2+1]]<dis[mode[i],heap[i]]) do
      if dis[mode[i*2],heap[i*2]]<dis[mode[i*2+1],heap[i*2+1]] then
        begin
          swap(rank[mode[i * 2],heap[i * 2]],rank[mode[i],heap[i]]);
          swap(mode[i],mode[i * 2]);
          swap(heap[i],heap[i * 2]);
          i:=i * 2;
        end
                                                               else
        begin
          swap(rank[mode[i * 2 + 1],heap[i * 2 + 1]],rank[mode[i],heap[i]]);
          swap(mode[i],mode[i * 2 + 1]);
          swap(heap[i],heap[i * 2 + 1]);
          i:=i * 2 + 1;
        end
end;

procedure spfa;
var
  who,now,i,j,k:longint;
begin
  while tot>0 do
    begin
      who:=heap[1];
      now:=mode[1];
      delete(now,who);
      k:=root[who];
      while k<>0 do
        begin
          if dis[now,who]+cost[k]<dis[0,point[k]] then
            begin
              swap(dis[0,point[k]],dis[1,point[k]]);
              count[1,point[k]]:=count[0,point[k]];
              dis[0,point[k]]:=dis[now,who]+cost[k];
              count[0,point[k]]:=count[now,who];
              delete(0,point[k]);
              delete(1,point[k]);
              insert(0,point[k]);
              insert(1,point[k]);
            end
                                                  else
          if dis[now,who]+cost[k]=dis[0,point[k]] then
            count[0,point[k]]:=count[0,point[k]]+count[now,who]
                                                  else
          if dis[now,who]+cost[k]<dis[1,point[k]] then
            begin
              dis[1,point[k]]:=dis[now,who]+cost[k];
              count[1,point[k]]:=count[now,who];
              delete(1,point[k]);
              insert(1,point[k]);
            end
                                                  else
          if dis[now,who]+cost[k]=dis[1,point[k]] then
            count[1,point[k]]:=count[1,point[k]]+count[now,who];
          k:=next[k];
        end;
    end;
end;

begin
  read(t);
  while t>0 do
    begin
      fillchar(root,sizeof(root),0);
      fillchar(heap,sizeof(heap),0);
      fillchar(mode,sizeof(mode),0);
      fillchar(dis,sizeof(dis),63);
      fillchar(count,sizeof(count),0);
      tot:=0;
      read(n,m);
      for i:=1 to m do
        begin
          read(a,b,l);
          connect(a,b,l);
        end;
      read(s,f);
      tot:=0;
      dis[0,s]:=0;
      count[0,s]:=1;
      insert(0,s);
      spfa;
      ans:=count[0,f];
      if dis[0,f]+1=dis[1,f] then ans:=ans+count[1,f];
      writeln(ans);
      dec(t);
    end;
end.
【上篇】
【下篇】

抱歉!评论已关闭.