zoukankan      html  css  js  c++  java
  • WordRings

    试题描述
    我们有 n 个字符串,每个字符串都是由 a 至 z 的小写英文字母组成的。如果字符串 A 的结尾两个字符刚好与字符串 B 的开头两个字符匹配,那么我们称 A 与 B 能够相连(注意:A 能与 B 相连不代表 B 能与 A 相连)。我们希望从给定的字符串中找出一些,使得它们首尾相连形成一个环串(一个串首尾相连也算),我们想要使这个环串的平均长度最大。如下例:
    ababc
    bckjaca
    caahoynaab
    第一个串能与第二个串相连,第二个串能与第三个串相连,第三个串能与第一个串相连,我们按照此顺序相连,便形成了一个环串,长度为 5+7+10=22(重复部分算两次),总共使用了 3 个串,所以平均长度是 22/3≈7.33
    输入
    本题有多组数据。
    每组数据的第一行,一个整数 n,表示字符串数量;
    接下来 n 行,每行一个长度小于等于 1000 的字符串。
    读入以 0 结束。
    输出
    若不存在环串,输出 No solution,否则输出最长的环串的平均长度。计算结果采用四舍五入。
    输入示例
    3
    intercommunicational
    alkylbenzenesulfonate
    tetraiodophenolphthalein
    0
    输出示例
    21.67
    其他说明
    数据范围与提示:对于全部数据,1≤n≤10^5。

     所以说有人告诉我不能用DFS

    于是写了DFS+SPFA+二分

    首先看到输出长度,还有10^5的数据,果断一波二分答案,然后写了BFS的SPFA,T了

    不知道为什么写DFS就能过

    连边是需要一点小技巧的,因为匹配的条件是两个字符相同,所以将两个字符作为一个顶点然后连边

    枚举的时候把所有的两个字符的组合都跑一遍就行了(我在想把这个优化一下是不是BFS就能过了)

    下面给出代码

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    inline int min(int a,int b){return a<b?a:b;}
    inline int max(int a,int b){return a>b?a:b;}
    inline int rd()
    {
        int x=0,f=1;
        char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    inline void write(int x)
    {
         if(x<0) putchar('-'),x=-x;
         if(x>9) write(x/10);
         putchar(x%10+'0');
    }
    char s[100006];
    int head[100006],nxt[100006],to[100006],v[100006];
    int total=0;
    double dis[100006];
    int book[100006];
    int calc(char a,char b){return (a-'a')*26+b-'a'+1;}//计算两个字符所对应的值 
    void add(int x,int y,int z)
    {
        total++;
        v[total]=z;
        to[total]=y;
        nxt[total]=head[x];
        head[x]=total;
        return ;
    }
    bool spfa(int x,double mid)
    {
        book[x]=1;
        for(int e=head[x];e;e=nxt[e])
        {
            if(dis[x]+v[e]-mid>dis[to[e]])
            {
                dis[to[e]]=dis[x]+v[e]-mid;
                if(book[to[e]]||spfa(to[e],mid))//判断是否存在环 
                {
                    book[to[e]]=0;
                    return 1;
                }
            }
        }
        book[x]=0;
        return 0;
    }
    bool check(double x)
    {
        memset(dis,0,sizeof(dis));
        for(int i=1;i<=26*26;++i) if(spfa(i,x)) return 1;//枚举所有前缀 
        return 0;
    }
    int main()
    {
        int n;
        while(cin>>n)
        {
            if(!n) break;
            total=0;
            memset(head,0,sizeof(head));
            for(int i=1;i<=n;i++)
            {
                cin>>s+1;
                int l=strlen(s+1);
                add(calc(s[1],s[2]),calc(s[l-1],s[l]),l);//以两个字符为点连边 
            }
            double l=0,r=1001;
            while(r-l>=1e-4)//二分答案 
            {
                double mid=(l+r)/2.0;
                if(check(mid)) l=mid;
                else r=mid;
            }
            if(l==0) printf("No solution
    ");
            else printf("%.2lf
    ",l);
        }
        return 0;
    }
    蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿
  • 相关阅读:
    hdu3874
    spoj D-query
    hdu4348
    hdu4417
    hdu2665
    [LUOGU] P1057 传球游戏
    [CODEVS] 2193 数字三角形WW
    [CODEVS] 2189 数字三角形W
    [模板] 线段树
    [模板] 树状数组
  • 原文地址:https://www.cnblogs.com/WWHHTT/p/9620832.html
Copyright © 2011-2022 走看看