单词接龙1
题目描述
Bsny从字典挑出N个单词,并设计了接龙游戏,只要一个单词的最后两个字母和另一个单词的前两个字母相同,那么这两个单词就可以有序的连接起来。
Bsny想要知道在所给的所有单词中能否按照上述方式接龙组成一个单词环(可能是多个),若能,求所有环的环中单词平均长度最大值。
输入
第一行一个整数N,表示单词数量。
接下来N行,每行一个字符串,仅包含小写字母。
输出
若能组成单词环,输出环中单词的最大平均长度,结果保留2位小数;否则输出”No solution.”(不包括双引号)。精度误差在0.01都算正确。
样例输入
3
intercommunicational
alkylbenzenesulfonate
tetraiodophenolphthalein
样例输出
21.67
提示
20%的数据:n≤20;
70%的数据:n≤1000;
100%的数据:n≤100000,每个单词长度不超过1000。输入数据比较大,C/C++的同学用scanf输入。
此题考试的时候并没有做出
好久没考试,都忘记了考试三件事:1.暴力2.二分3.LCA
此题只需二分答案,再用splay判是否有环
Double变量以带符号的IEEE64位(8个字节)双精度浮点数形式存储,取值范围如下:
负值取值范围为−1.79769313486231570E+308到−4.94065645841246544E−324;
正值取值范围为4.94065645841246544E−324到1.79769313486231570E+308。
超级无敌大,有没有!!!,是指数级的!!!!!!!
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char ch[1050];
double dis[1000],val[500050],val1[500050];
int hed[1000],vet[500050],Next[500050],q[5000500],inq[1000];
bool inn[1000],flag[1000],ff[1000];
int num;
int nn;
void add(int u,int v,int len){
++num;
vet[num]=v;
val[num]=len;
//cout<<num<<" "<<val[num]<<endl;
val1[num]=len;
//cout<<val[num]<<endl;
Next[num]=hed[u];
hed[u]=num;
}
bool spfa(int x){
for (int i=0;i<=675;++i) dis[i]=-100000000000,inn[i]=false;
int head=0,tail=0;
q[head]=x;
inn[x]=true;
dis[x]=0;
while (head<=tail){
int u=q[head];
ff[u]=false;
++head;
inn[u]=false;
for (int i=hed[u];i!=-1;i=Next[i]){
int v=vet[i];
if (dis[u]+val[i]>dis[v]){
dis[v]=dis[u]+val[i];
if (inn[v]==false){
inn[v]=true;
++tail;
q[tail]=v;
++inq[v];
if (inq[v]>=nn) return 1;
}
}
}
}
return 0;
}
bool check(int x){
for (int i=0;i<=675;++i) {ff[i]=true;inq[i]=0;}
//cout<<"ha"<<endl;
for (int i=0;i<=675;++i)
if (flag[i]&&ff[i]){
if (spfa(i)) return 1;
}
return 0;
}
int main(){
int n;
scanf("%d",&n);
for (int i=0;i<=675;++i) {hed[i]=-1;flag[i]=false;}
num=0;
nn=0;
for (int i=1;i<=n;++i){
scanf("%s",ch);
int len=strlen(ch);
int u=(ch[0]-'a')*26+(ch[1]-'a');
int v=(ch[len-2]-'a')*26+(ch[len-1]-'a');
add(u,v,len);
if (flag[u]==false) ++nn;
if (flag[v]==false) ++nn;
flag[u]=true;
flag[v]=true;
}
double l=1;
double r=1000;
while (r-l>0.001){
double mid=(l+r)/2;
for (int i=1;i<=n;++i) val[i]=val1[i]-mid;
//for (int i=1;i<=n;++i) cout<<val1[i]<<" "<<mid<<" "<<val[i]<<endl;
//cout<<endl;
if (check(1)) l=mid;else r=mid;
}
if (l>1) printf("%.2lf\n",l);
else printf("No solution.\n");
return 0;
}