1. 题目
聚会 (FTT)
【问题描述】
小S想要从某地出发去同学k的家中参加一个party,但要有去有回。他想让所用的时间尽量的短。但他又想知道从不同的点出发,来回的最短时间中最长的时间是多少,
这个任务就交给了你。
【输入格式】
第一行三个正整数n,m,k(n是节点个数,m是有向边的条数,k是参加聚会的地点编号)( 1 ≤ N ≤ 1000 ,1 ≤ M ≤ 100,000)
第二行..m+1行每行3个整数x,y,w 代表从x到y需要花w的时间(1 ≤ w≤ 100)
【输出格式】
输出从不同的节点出发的最短时间中最长的时间。
【样例输入】party.in
4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3
【样例输出】party.out
10
2. 题目实质
其实这个东西就是一个最短路的模型。
3. 算法
我说是网络流......你信不?
废话,当然是最短路!
每个点到K节点的最短路 + K到对应的点的最短路
以除K以外的点到K的最短路反复的求就有了很多的冗余,会超时
可以思考从其他的点到K点的最短路等价于从K点出发使用反向边求到各个点的最短路
这样这道题就完美的解决了 ans=max{dis1[i][k]+dis2[i][k]}
4. 注意事项
注意,这个题是非常典型的需要正着求一遍,反着求一遍的最短路。
5. 代码
水水最短路 (Leve)
var
n,m,k,i,j,ans:longint;
x,y,len:longint;
d:array[1..1000] of longint;
sum:array[1..1000] of longint;
map,mapp:array[1..1000,0..1000] of longint;
ll,lll:array[1..1000,1..1000] of longint;
q:array[1..1000000] of longint;
v:array[1..1000] of boolean;
procedure spfa(x:longint);
var
i,l,r,temp:longint;
begin
filldword(d,sizeof(d)>>2,maxlongint>>1);
fillchar(v,sizeof(v),false);
v[x]:=true;
l:=0; r:=1;
d[x]:=0;
q[1]:=x;
while l<r do
begin
inc(l);
temp:=q[l];
v[temp]:=false;
for i:=1 to map[temp,0] do
if d[map[temp,i]]>d[temp]+ll[temp,i] then
begin
d[map[temp,i]]:=d[temp]+ll[temp,i];
if not v[map[temp,i]] then
begin
v[map[temp,i]]:=true;
inc(r);
q[r]:=map[temp,i];
end;
end;
end;
end;
procedure spfa2(x:longint);
var
i,l,r,temp:longint;
begin
filldword(d,sizeof(d)>>2,maxlongint>>1);
fillchar(v,sizeof(v),false);
v[x]:=true;
l:=0; r:=1;
d[x]:=0;
q[1]:=x;
while l<r do
begin
inc(l);
temp:=q[l];
v[temp]:=false;
for i:=1 to mapp[temp,0] do
if d[mapp[temp,i]]>d[temp]+lll[temp,i] then
begin
d[mapp[temp,i]]:=d[temp]+lll[temp,i];
if not v[mapp[temp,i]] then
begin
v[mapp[temp,i]]:=true;
inc(r);
q[r]:=mapp[temp,i];
end;
end;
end;
end;
begin
assign(input,'party.in');
assign(output,'party.out');
reset(input);
rewrite(output);
readln(n,m,k);
for i:=1 to m do
begin
readln(x,y,len);
inc(map[x,0]);
map[x,map[x,0]]:=y;
ll[x,map[x,0]]:=len;
inc(mapp[y,0]);
mapp[y,mapp[y,0]]:=x;
lll[y,mapp[y,0]]:=len;
end;
spfa(k);
for i:=1 to n do
sum[i]:=d[i];
spfa2(k);
for i:=1 to n do
if i<>k then
if d[i]<maxlongint>>1 then
if sum[i]<maxlongint>>1 then
if d[i]+sum[i]>ans then ans:=d[i]+sum[i];
writeln(ans);
close(input);
close(output);
end.