【ZJOI2017 Round1练习&BZOJ4773】D3T1 cycle(最小负环,倍增)

题意:给定一个带权有向图,求点数最小的负环。

2 n 300
0 m n(n - 1)
1 ui,vi n
abs(w[j])<= 10^4

思路:倍增思想

设d[i,j,k]为走不多于2^i次步,从j走到k的最小权值和

显然d[i]可以由d[i-1]推出

f[i,j]表示当前走若干步后从i到j的最小权值和

从大到小枚举在原来的基础上再走不多于2^i步的结果

如果有负环就不用再走2^i步,将f复原

否则将j更新为走2^i步之后的数值,继续枚举

 1 const oo=1000000000;
 2 var d:array[0..9,1..300,1..300]of longint;
 3     g,f:array[1..300,1..300]of longint;
 4     n,m,i,j,k,t,ans,x,y,z:longint;
 5     flag:boolean;
 6 
 7 function min(x,y:longint):longint;
 8 begin
 9  if x<y then exit(x);
10  exit(y);
11 end;
12 
13 begin
14  assign(input,'cycle.in'); reset(input);
15  assign(output,'cycle.out'); rewrite(output);
16  readln(n,m);
17  for i:=1 to n do
18   for j:=1 to n do
19    if i<>j then d[0,i,j]:=oo;
20  for i:=1 to m do
21  begin
22   readln(x,y,z);
23   d[0,x,y]:=min(d[0,x,y],z);
24  end;
25  for t:=1 to 8 do
26  begin
27   for i:=1 to n do
28    for j:=1 to n do
29     if i<>j then d[t,i,j]:=oo;
30   for i:=1 to n do
31    for j:=1 to n do
32     for k:=1 to n do d[t,i,k]:=min(d[t,i,k],d[t-1,i,j]+d[t-1,j,k]);
33  end;
34  for i:=1 to n do
35   for j:=1 to n do
36    if i<>j then f[i,j]:=oo;
37  for t:=8 downto 0 do
38  begin
39   for i:=1 to n do
40    for j:=1 to n do g[i,j]:=f[i,j];
41   for i:=1 to n do
42    for j:=1 to n do
43     for k:=1 to n do f[i,k]:=min(f[i,k],g[i,j]+d[t,j,k]);
44   flag:=false;
45   for i:=1 to n do
46    if f[i,i]<0 then begin flag:=true; break; end;
47   if flag then
48   begin
49    for i:=1 to n do
50     for j:=1 to n do f[i,j]:=g[i,j];
51   end
52    else ans:=ans+(1<<t);
53  end;
54  inc(ans);
55  if ans>n then writeln(0)
56   else writeln(ans);
57 
58  close(input);
59  close(output);
60 end.

 

posted on 2017-03-07 14:44  myx12345  阅读(317)  评论(0编辑  收藏  举报

导航