zoukankan      html  css  js  c++  java
  • Word Rings

    https://loj.ac/problem/10082

    题目描述

      给出若干字符串,如果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
    ",ans);
            else printf("No solution
    ");
        }
        return 0;
    }
  • 相关阅读:
    PAT (BL) 1001
    mysql启动报错:/usr/bin/mysqld_safe: line 183: 17006 Killed nohup /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin......
    动态规划:某个单词增加,删除,替换字母而成为另一个单词的最小变更次数?
    ng-class最好用的一种方法
    java数据结构基本框架
    后台运行tomcat和mysql的方法
    mysql无法开启,报错:MySQL Daemon failed to start.
    linux CentOS6.5 yum安装mysql 5.6
    idea mybatis报错:<statement> or DELIMITER expected, got 'id'
    angularjs $http与springmvc @RequestBody
  • 原文地址:https://www.cnblogs.com/fangbozhen/p/11695191.html
Copyright © 2011-2022 走看看