Description
给出一个有n个顶点m条边的有向图,对于一条边长度为len的边有两种走法。
1、如果a和b可以互达,则走过这条边的时间为len
2、如果a和b不可以互达,则走过这条边的时间为2*len
现在给出一个k,问,从顶点1到顶点n,满足第二种走法不超过k次的最短时间是多少。
Input
第一行有3个整数n,m,k(1<=n<=100,1<=m<=10000,0<=k<=10),表示有n个顶点,m条边。
接下来有m行,每行有3个整数xi,yi,leni(1<=xi,yi<=n,1<=leni<=10000),表示长度为leni的有向边。
注意,两个点可能有多条边连接。
Output
一行一个整数,表示最短时间。
如果没有满足题目条件的路径,则输出-1
Sample Input
7 7 3
1 2 2
1 3 2
2 4 3
4 7 5
3 5 4
5 6 1
6 4 2
Sample Output
20
Data Constraint
Hint
【数据约定】
对于30%的数据n<=10,m<=10,
对于100%的数据,如题目描述
题解
这道题看起来很难,实际上真的很(jian)难(dan)!
对于这题,因为数据范围很小,所以可以先用 Floyd 求是否连通,再把不连通的边 * 2 。在对于整个图跑一遍 SPFA和分层图,边跑变更新答案,就可以了。
分层图(拆点(二维dis))+spfa+floyd(预处理互达)
P.S:预处理可以用的遍历,也可以用
的Floyd【数据过水,N才100】
CODE
uses math;
var
n,m,t,i,j,k,ans:longint;
p,d,map,f:array[0..1000,0..1000]of longint;
bz:array[0..1000,0..1000]of boolean;
x,y,len:array[0..2000]of longint;
procedure spfa();
var
l,r,x,y,i,pp:longint;
begin
fillchar(d,sizeof(d),0);
fillchar(bz,sizeof(bz),false);
fillchar(f,sizeof(f),127);
f[1,0]:=0;bz[1,0]:=true;d[1,1]:=1;d[1,2]:=0;
l:=1;r:=1;
while l<=r do begin
x:=d[l,1];
y:=d[l,2];
for i:=1 to n do
if map[x,i]<>0 then begin
if p[i,x]=1 then pp:=0 else pp:=1;
if f[i,y+pp]>map[x,i]+f[x,y] then begin
f[i,y+pp]:=map[x,i]+f[x,y];
if not bz[i,y+pp] then begin
inc(r);
d[r,1]:=i;
d[r,2]:=y+pp;
bz[i,y+pp]:=true;
end;
end;
end;
bz[k,j]:=false;
inc(l);
end;
end;
begin
readln(n,m,t);
for i:=1 to n do begin
readln(x[i],y[i],len[i]);
map[x[i],y[i]]:=len[i];
end;
for i:=1 to n do
for j:=1 to n do
for k:=1 to n do
if (i<>j)and(i<>k)and(j<>k) then
if map[i,k]+map[k,j]<map[i,j] then
map[i,j]:=map[i,k]+map[k,j];
fillchar(p,sizeof(p),1);
for i:=1 to n do
for j:=1 to n do
if (map[i,j]<>0)and(map[j,i]=0) then begin
map[i,j]:=map[i,j]*2;
//map[j,i]:=map[j,i]*2;
p[i,j]:=2;
//p[j,i]:=2;
end;
spfa;
ans:=maxlongint;
for i:=0 to k do ans:=min(ans,f[n,i]);
if ans=maxlongint then
writeln(-1)
else
writeln(ans);
end.
P.S:不要开maxlongint(太大),会卡-1。