Elaxia的路线(travel)

Elaxia的路线
问题描述:
最近,Elaxia 和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,
他们必须合理地安排两个人在一起的时间。Elaxia 和w**每天都要奔波于宿舍和实验室之间,
他们希望在节约时间的前提下,一起走的时间尽可能的长。
现在已知的是Elaxia 和w**所在的宿舍和实验室的编号以及学校的地图:地图上有N
个路口,M 条路,经过每条路都需要一定的时间。
具体地说,就是要求无向图中,两对点间最短路的最长公共路径。
输入格式:
第一行:两个整数N 和M(含义如题目描述)。
第二行:四个整数x1、y1、x2、y2(1 ≤ x1 ≤ N,1 ≤ y1 ≤ N,1 ≤ x2 ≤ N,
1 ≤y2 ≤ N),分别表示Elaxia 的宿舍和实验室及w**的宿舍和实验室的标号(两对点分
别为x1,y1 和x2,y2)。
接下来M 行:每行三个整数,u、v、l(1 ≤ u ≤ N,1 ≤ v ≤ N,1 ≤ l ≤ 10000),
表示u 和v 之间有一条路,经过这条路所需要的时间为l。

输出格式:
一行,一个整数,表示每天两人在一起的时间(即最长公共路径的长度)。
样例输入:
9 10
1 6 7 8
1 2 1
2 5 2
2 3 3
3 4 2
3 9 5
4 5 3
4 6 4
4 7 2
5 8 1
7 9 1
样例输出:
3
数据范围:
对于30%的数据,N ≤ 100;
对于60%的数据,N ≤ 1000;
对于100%的数据,N ≤ 1500,输入数据保证没有重边和自环。


对于x1,x2,y1,y2各做一遍最短路

所有满足(dis[x1,i]+dis[x2,i]=dis[x1,x2])and(dis[y1,i]+dis[y2,i]=dis[y1,y2])的点都在两条最短路的公共路上

然后枚举点对(i,j)

若(abs(dis[x1,i]-dis[x1,j])=abs(dis[x2,i]-dis[x2,j]))and(abs(dis[y1,i]-dis[y1,j])=abs(dis[y2,i]-dis[y2,j]))and(abs(dis[x1,i]-dis[x1,j])=abs(dis[y1,i]-dis[y1,j]))

则abs(dis[x1,i]-dis[x1,j])为一种答案,记录最大的即可

虽然(i,j)可能不在一条最短路上,但若abs(dis[x1,i]-dis[x1,j])相同,则j与i对应的最大点k等价,所以答案不变

错误:对每个点进行了一遍最短路,浪费了时间,没有彻底分析


program travel;
type
  arr=array [0..1501] of longint;
var
  ans,tot,n,m,i,j,k,x1,y1,x2,y2,u,v,l:longint;
  dl,heap,rank:array [0..30001] of longint;
  root:array [0..1501] of longint;
  next,point,cost:array [0..3000001] of longint;
  dis:array [0..1501] of arr;

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

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

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

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

procedure spfa (now:longint);
var
  i,j,k:longint;
begin
  for i:=1 to tot do
    heap[i]:=0;
  fillchar(rank,sizeof(rank),0);
  tot:=0;
  dis[now,now]:=0;
  insert(now,dis[now]);
  while tot>0 do
    begin
      j:=heap[1];
      delete(heap[1],dis[now]);
      k:=root[j];
      while k<>0 do
        begin
          if (dis[now][j]+cost[k]<dis[now][point[k]]) then
            begin
              if rank[point[k]]<>0 then delete(point[k],dis[now]);
              dis[now][point[k]]:=dis[now][j]+cost[k];
              insert(point[k],dis[now]);
            end;
          k:=next[k];
        end;
    end;
end;

begin
  assign(input,'travel.in');
  reset(input);
  assign(output,'travel.out');
  rewrite(output);
  read(n,m);
  read(x1,x2,y1,y2);
  for i:=1 to m do
    begin
      if i=1500 then
        begin
          j:=1;
        end;
      read(u,v,l);
      connect(u,v,l);
      connect(v,u,l);
    end;
  tot:=0;
  fillchar(dis,sizeof(dis),63);
  spfa(x1);
  spfa(x2);
  spfa(y1);
  spfa(y2);
  tot:=0;
  for i:=1 to n do
    if (dis[x1,i]+dis[x2,i]=dis[x1,x2])and(dis[y1,i]+dis[y2,i]=dis[y1,y2]) then
      begin
        inc(tot);
        dl[tot]:=i;
      end;
  ans:=0;
  for i:=1 to tot do
    for j:=1 to tot do
      if (abs(dis[x1,dl[i]]-dis[x1,dl[j]])=abs(dis[x2,dl[i]]-dis[x2,dl[j]]))
      and(abs(dis[y1,dl[i]]-dis[y1,dl[j]])=abs(dis[y2,dl[i]]-dis[y2,dl[j]]))
      and(abs(dis[x1,dl[i]]-dis[x1,dl[j]])=abs(dis[y2,dl[i]]-dis[y2,dl[j]])) then
        if ans<abs(dis[y2,dl[i]]-dis[y2,dl[j]]) then ans:=abs(dis[y2,dl[i]]-dis[y2,dl[j]]);
  writeln(ans);
  close(input);
  close(output);
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值