您的位置:首页 > 其它

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

2017-03-07 14:44 288 查看

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

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.

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: