您的位置:首页 > 其它

【NOIP2014八校联考第2场第2试】单词接龙

2017-01-14 21:38 393 查看

题目

Description

Bsny从字典挑出N个单词,并设计了接龙游戏,只要一个单词的最后两个字母和另一个单词的前两个字母相同,那么这两个单词就可以有序的连接起来。

Bsny想要知道在所给的所有单词中能否按照上述方式接龙组成一个单词环(可能是多个),若能,求所有环的环中单词平均长度最大值。

Input

第一行一个整数N,表示单词数量。

接下来N行,每行一个字符串,仅包含小写字母。

Output

若能组成单词环,输出环中单词的最大平均长度,结果保留2位小数;否则输出”No solution.”(不包括双引号)。精度误差在0.01都算正确。

Sample Input

3

intercommunicational

alkylbenzenesulfonate

tetraiodophenolphthalein

Sample Output

21.67

Data Constraint

20%的数据:n≤20;

70%的数据:n≤1000;

100%的数据:n≤100000,每个单词长度不超过1000。输入数据比较大,C/C++的同学用scanf输入。

题解

第一眼看到是平均数首先就确定了二分

然后发现这个东西可以转化成一共有262个点的有向图

那么这种类型的题目有一个标准的做法:

二分

然后把每一条边减去mid,如果这个时候出现了正环,那么说明我们的mid还不够大,l=mid+1否则r=mid

判断正环的话考虑到复杂度为KE的SPFA,很多人说要一个点过n次才可以判断出有正环

但是这样好慢啊

怎么办呢

上网搜一下,SPFA中的E在最稠密的图之中大小为4(格子图除外)(详情见网上证明)

所以当当前宽搜的点已经超过4*边数那么我们就可以退出了

贴代码

const
dou=26;
vg=702;
var
//p:array[0..100005,1..3]of longint;
map,map1:array[0..705,0..705]of longint;
tot,tot1:array[0..705,0..705]of longint;
ju:array[0..705]of longint;
h:array[0..1000005]of longint;
bz,bb:array[0..100005]of boolean;
s:ansistring;
i,j,k,l,n,m,x,y,z,r,mid,cc,top:longint;
function check:boolean;
var
i,j,k,n,p,x,z:longint;
begin
fillchar(bz,sizeof(bz),false);
fillchar(bb,sizeof(bb),false);
for z:=1 to vg do
if bb[z]=false then
begin
bz[z]:=true;
bb[z]:=true;
fillchar(ju,sizeof(ju),128);
i:=1;
j:=0;
h[i]:=z;
ju[z]:=0;
while i>j do
begin
inc(j);
for k:=1 to map1[h[j],0] do
begin
x:=map1[h[j],k];
if ju[h[j]]+tot1[h[j],k]>ju[x] then
begin
ju[x]:=ju[h[j]]+tot1[h[j],k];
if bz[x]=false then
begin
inc(i);
h[i]:=x;
bz[x]:=true;
bb[x]:=true;
end;
end;
end;
bz[h[j]]:=false;
if i>10*vg then exit(false);
end;
end;
exit(true);
end;
begin
//assign(input,'t1.in'); reset(input);
readln(n);
for i:=1 to n do
begin
readln(s);
x:=ord(s[1])-96+(ord(s[2])-96)*dou;
//p[i,1]:=x;
y:=x;
m:=length(s);
x:=ord(s[m-1])-96+(ord(s[m])-96)*dou;
//p[i,2]:=x;
map[y,x]:=1;
if m*1000>tot[y,x] then
tot[y,x]:=m*1000;
end;
l:=1;
r:=1000*1000;
while l<r do
begin
mid:=(l+r) div 2;
for i:=1 to vg do
begin
map1[i,0]:=0;
for j:=1 to vg do
if map[i,j]=1 then
begin
inc(map1[i,0]);
map1[i,map1[i,0]]:=j;
tot1[i,map1[i,0]]:=tot[i,j]-mid;
end;
end;
if check then r:=mid else l:=mid+1;
end;
writeln((l/1000):0:2);
// close(input);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: