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.