单词接龙1

单词接龙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

DoubleIEEE648:

1.79769313486231570E+3084.94065645841246544E324

4.94065645841246544E3241.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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值