【POJ2949】Word Rings(最大平均值环)

题意:给定N个字符串,如果A串的最后两个字母跟B串的前两个字母相同它们就能连接。

求一个由字符串组成的首尾相连的环,使(字符串总长度/字符串个数)最大。

n<=100000 len<=1000

思路:SPFA国家队论文题

赋所有dis[i]=0,跑最长路,如果某个元素入队次数超过点数就说明有正环。

使用DFS版本的SPFA做比BFS快10倍,为什么?

论文里高大上看不懂,蒟蒻用简单粗暴的方法想了一下:

如果某个环有K个点组成,BFS会从K个点中的某个点开始,每次都换一个点扩展一次,可能达到O(N*K^2)

DFS则只选其中的一个点不断扩展,K次就能使自己重新入队一次,这样就是O(N*K)

孰优孰劣一眼分明

以下是论文原文,用来证明初始值=0的正确性

 1 var q:array[0..2000000]of longint;
 2     dis:array[1..2000]of double;
 3     head,vet,next,len,time,inq:array[1..150000]of longint;
 4     n,m,tot,i,x,y,k:longint;
 5     l,r,mid,last,eps:double;
 6     ch:ansistring;
 7 
 8 procedure add(a,b,c:longint);
 9 begin
10  inc(tot);
11  next[tot]:=head[a];
12  vet[tot]:=b;
13  len[tot]:=c;
14  head[a]:=tot;
15 end;
16 
17 function spfa(k:double):boolean;
18 var u,top,i,e,v:longint;
19 begin
20  top:=0;
21  for i:=1 to 27*27 do
22  begin
23   inq[i]:=0; dis[i]:=0; time[i]:=0;
24  end;
25  for i:=1 to 27*27 do
26   if head[i]>0 then
27   begin
28    inc(top); q[top]:=i; inq[i]:=1; inc(time[i]);
29   end;
30  while top>0 do
31  begin
32   u:=q[top]; dec(top);
33   inq[u]:=0;
34   e:=head[u];
35   while e<>0 do
36   begin
37    v:=vet[e];
38    if dis[u]+len[e]-k>dis[v] then
39    begin
40     dis[v]:=dis[u]+len[e]-k;
41     if inq[v]=0 then
42     begin
43      inc(top); q[top]:=v; inq[v]:=1;
44      inc(time[v]);
45      if time[v]>n then exit(true);
46     end;
47    end;
48    e:=next[e];
49   end;
50  end;
51  exit(false);
52 end;
53 
54 begin
55  assign(input,'poj2949.in'); reset(input);
56  assign(output,'poj2949.out'); rewrite(output);
57  while not eof do
58  begin
59   readln(n);
60   if n=0 then exit;
61   fillchar(head,sizeof(head),0); tot:=0;
62   for i:=1 to n do
63   begin
64    readln(ch); k:=length(ch);
65    x:=(ord(ch[1])-ord('a'))*27+ord(ch[2])-ord('a')+1;
66    y:=(ord(ch[k-1])-ord('a'))*27+ord(ch[k])-ord('a')+1;
67    add(x,y,k);
68   end;
69   n:=0;
70   for i:=1 to 27*27 do
71    if head[i]>0 then inc(n);
72   l:=0; r:=1000; last:=0;
73   eps:=1e-5;
74   while r-l>eps do
75   begin
76    mid:=(l+r)/2;
77    if spfa(mid) then begin last:=mid; l:=mid; end
78     else r:=mid;
79   end;
80   if last<eps then writeln('No solution.')
81    else writeln(last:0:2);
82 
83  end;
84  close(input);
85  close(output);
86 end.
原文地址:https://www.cnblogs.com/myx12345/p/6212893.html