Word Rings
时间:2019-10-20
本文章向大家介绍Word Rings,主要包括Word Rings使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目描述
给出若干字符串,如果A的末2个字符和B的首2个字符相同,那么称A和B相连,求从给定的字符串中找出一条环串使串的平均长度最短。
思路
首先我们考虑建图,显然,以字符串为点的图难以实现,而两个字符最多只有26×26个节点,那么字符串就是连接两个节点的边,其边权即为串的长度。接下来我们考虑如何求串的平均长度。
假设串的平均长度为average,那么我们有等式:
(s1-average)+(s2-average)...(sn-average)=0。
由此我们可以知道这个average具有单调性,若把每条边的边权减去average后存在一个正环,那么就把二分的答案减小。
不过如果用常规的spfa求环,很可能会T,被卡到上界。我们考虑这里并不需要每个点的最短路,因此完全可以不用bfs,而用dfs。而为何能用dfs,因为查找正环和最短路不一样,我们不用正确的最短路,而是一个点的被更新次数,并且dfs很可能通过访问从一个点出发重新到达一个点,因此效率相比较bfs大大提高了。我们还可以进行优化,如果dis[x]>最大边权*边数,显然就出现了正环。
代码
#include <bits/stdc++.h> using namespace std; const int N=1e5+10; const double eps=1e-4; int nxt[N],head[N],to[N],vis[N],tot; double dis[N],w[N],maxe; int f,alpha[N]; char s[1100]; void add_edge(int x,int y,double v) { nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; w[tot]=v; } void spfa(int u,int h,double aver) { if(f)return ; vis[u]=h; for(int i=head[u];~i;i=nxt[i]) { int v=to[i]; if(dis[u]+w[i]-aver>dis[v]) { dis[v]=dis[u]+w[i]-aver; if(dis[v]>maxe){f=1;return ;}//最大边权 if(!vis[v])spfa(v,h,aver); if(vis[v]==h){f=1;return ;}//已在dfs中访问过 } } vis[u]=0; } bool check(double aver) { memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); f=0; for(int i=1;i<=tot;i++) { spfa(i,i,aver); if(f)break ; } return f; } int main() { int n,idx; while(~scanf("%d",&n)) { tot=0;maxe=0;idx=0; memset(alpha,0,sizeof(alpha)); memset(head,-1,sizeof(head)); if(n==0)break ; for(int i=1;i<=n;i++) { scanf(" %s",s); int len=strlen(s); maxe=max(maxe,(double)len); int x=(s[0]-'a')*26+s[1]-'a'; int y=(s[len-2]-'a')*26+s[len-1]-'a'; if(!alpha[x])alpha[x]=++idx; int id1=alpha[x]; if(!alpha[y])alpha[y]=++idx; int id2=alpha[y]; add_edge(id1,id2,len); } maxe=maxe*n; double l=0,r=1000,ans=-1; while(r-l>eps) { // cout<<r<<' '<<l<<endl; double mid=(l+r)/2; if(check(mid))ans=mid,l=mid; else r=mid; } if(ans!=-1)printf("%.3lf\n",ans); else printf("No solution\n"); } return 0; }
原文地址:https://www.cnblogs.com/fangbozhen/p/11695191.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android配置文件操作模块封装,全互联网最简单好用的封装
- 使用logcat让Android应用支持查看实时日志并输出至界面显示功能
- 如何处理redis集群的hot key和big key
- 嵌入式linux之go语言开发(十一)让web服务器跑在终端上,通过网页配置终端参数
- 嵌入式linux之go语言开发(十二)参数配置文件存储模块开发
- 嵌入式linux之go语言开发(十三)LittlevGL,漂亮的嵌入式GUI的go语言绑定
- 同事问我MySQL怎么递归查询,我懵逼了...
- RocketMQ学习四-生产者producer
- 想有自己的博客吗?浏览器支持 MarkDown和语法高亮的最简单示例(使用markdown-it、highlight.js和mermaid)
- Golang--Go语言 五百行后台代码实现一简约的个人博客网站-TinyBlog
- RocketMQ学习5
- c语言调用go封装的动态库步骤及减小体积包的方法
- 深入理解JavaScript闭包之闭包的使用场景
- Spring Boot 到底是个啥?
- Spring Boot 整合 Thymeleaf