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

来源:互联网 发布:mendeley for mac 编辑:程序博客网 时间:2024/05/17 02:51

题目

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.
0 0
原创粉丝点击