1486: [HNOI2009]最小圈 - BZOJ

时间:2023-03-10 07:10:38
1486: [HNOI2009]最小圈 - BZOJ
1486: [HNOI2009]最小圈 - BZOJ1486: [HNOI2009]最小圈 - BZOJ
在机房的小伙伴提醒是二分之后,我想到了是判负环,所以我用spfa,而且我保持dis都是小于等于0,本以为这样就能过了,可是还是有一个点达到了3.8s左右(其他都是0.0几秒)
所以还是写了dfs版本,还是一样每次都保持dis小于等于0,当发现有一个点在栈中,你又可以更新他的dis,那么就有负环了
 const
maxn=;
maxm=;
inf=;
var
first:array[..maxn]of longint;
next,last:array[..maxm]of longint;
w:array[..maxm]of double;
n,m:longint; procedure init;
var
i,x:longint;
begin
read(n,m);
for i:= to m do
begin
read(x);
read(last[i],w[i]);
next[i]:=first[x];
first[x]:=i;
end;
end; var
flag,vis:array[..maxn]of longint;
dis:array[..maxn]of double;
time,time2:longint;
ans:double; function dfs(x:longint;f:double):boolean;
var
i:longint;
begin
flag[x]:=time;
vis[x]:=time2;
dis[x]:=f;
i:=first[x];
while i<> do
begin
if f+w[i]-ans<= then
begin
if vis[last[i]]=time2 then
if dis[last[i]]>=f+w[i]-ans then exit(true);
if vis[last[i]]<>time2 then
if dfs(last[i],f+w[i]-ans) then exit(true);
end;
i:=next[i];
end;
vis[x]:=time2-;
exit(false);
end; procedure work;
var
i:longint;
l,r:double;
f:boolean;
begin
l:=-;
r:=-l;
while r-l>1e-9 do
begin
ans:=(l+r)/;
inc(time);
f:=false;
for i:= to n do
if flag[i]<>time then
begin
inc(time2);
if dfs(i,) then
begin
f:=true;
break;
end;
end;
if f then r:=ans
else l:=ans;
end;
writeln(ans::);
end; begin
init;
work;
end.