• Word Rings


    传送门

    我们有$n$个字符串,每个字符串都是由$a$至$z$的小写英文字母组成的。如果字符串$A$的结尾两个字符刚好与字符串$B$的开头两个字符匹配,那么我们称$A$与$B$能够相连(注意:$A$能与$B$相连不代表$B$能与$A$相连)。

    我们希望从给定的字符串中找出一些,使得它们首尾相连形成一个环串(一个串首尾相连也算),使这个环串的平均长度最大。如下例:

    ababc
    bckjaca
    caahoynaab

    第一个串能与第二个串相连,第二个串能与第三个串相连,第三个串能与第一个串相连,我们按照此顺序相连,便形成了一个环串,长度为$5+7+10=22$(重复部分算两次),总共使用了$3$个串,所以平均长度是$frac{22}{3} approx 7.33$。

    解析

    《SPFA算法的优化及应用》

    建图:把单词看成边,把首尾字母组合看成点。例如:对于单词$ababc$就是点"$ab$"向点"$bc$"连一条长度为$5$的边。

    二分答案:二分平均长度$ave$。

    SPFA:将图中每条边的权值减去$ave$,题目转换为查找图中是否存在正环,采用 DFS 版的 SPFA 

    代码

     1 #include<bits/stdc++.h>
     2 #define eps 1e-4
     3 using namespace std;
     4 const int N=3005,M=1e4+5;
     5 int n,tot,cnt,hsh[N],fro[N];
     6 double dis[N];
     7 bool vis[N];
     8 char s[1005];
     9 struct edge{int to,w,nxt;}e[M<<1];
    10 void add(int x,int y,int z) {
    11     e[++cnt].to=y,e[cnt].w=z,e[cnt].nxt=fro[x]; fro[x]=cnt;
    12 }
    13 
    14 bool SPFA(int u,double ave) {
    15     vis[u]=1;
    16     for(int i=fro[u];i;i=e[i].nxt) {
    17         int v=e[i].to;
    18         if(dis[v]<dis[u]+e[i].w-ave) {
    19             dis[v]=dis[u]+e[i].w-ave;
    20             if(vis[v]) return 1;
    21             if(SPFA(v,ave)) return 1;
    22         }
    23     }
    24     return vis[u]=0;
    25 }
    26 
    27 bool check(double ave) {
    28     fill(dis,dis+tot+1,0);
    29     fill(vis,vis+tot+1,0);
    30     for(int i=1;i<=tot;i++)
    31      if(SPFA(i,ave)) return 1;
    32     return 0;
    33 }
    34 
    35 int main() {
    36     while(scanf("%d",&n),n) {
    37         tot=cnt=0;
    38         memset(hsh,0,sizeof(hsh));
    39         memset(fro,0,sizeof(fro));
    40         for(int i=1;i<=n;i++) {
    41             scanf("%s",s);
    42             int len=strlen(s);
    43             int a=(s[0]-'a')*26+s[1]-'a';
    44             int b=(s[len-2]-'a')*26+s[len-1]-'a';
    45             if(!hsh[a]) hsh[a]=++tot;
    46             if(!hsh[b]) hsh[b]=++tot;
    47             add(hsh[a],hsh[b],len);
    48         }
    49         double l=0,r=1e3,ans=-1;
    50         while(r-l>eps) {
    51             double Mid=(l+r)/2;
    52             if(check(Mid)) l=Mid,ans=Mid;
    53             else r=Mid;
    54         }
    55         if(ans==-1) printf("No solution
    ");
    56         else printf("%.2lf
    ",ans);    
    57     }
    58 }
  • 相关阅读:
    Javascript的作用域、作用域链以及闭包
    C#当中的泛型和java中的对比
    MongoDB的主从复制和副本集
    MongoDB启动配置等
    JavaScript学习系列1 基础-变量
    Umbraco项目发布错误 --More than one type want to be a model for content type authorize
    项目中gulp使用发生的错误及解决
    JavaScript学习系列2一JavaScript中的变量作用域
    ASP.NET MVC中的ActionFilter介绍学习
    Razor中的 内容标记块语法
  • 原文地址:https://www.cnblogs.com/qq8260573/p/10387074.html
Copyright © 2020-2023  润新知