ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[SP2885]WORDRING - Word Rings

2019-04-07 09:37:36  阅读:221  来源: 互联网

标签:SP2885 Word int double Rings mid rb lb now


题意就不解释了。。

咋一看,似乎没什么头绪。

但是,我们可能会注意环串这个字。

环的概念一般在图论中出现,所以这里显然就用到了图的思想。

建图

我们可以把每个字符串的前两个和后两个字符作为顶点,将字符串看作边,那么最多有\(26^2\)个点,边的长度即为字符串长度。

注意我们要忽略长度为\(1\)的字符串。


然后我们又会注意到:平均长度最长,所以我们很容易想到二分。

二分

  • 我们假设答案为\(mid \in (0,1000)\),下界\(lb=-1\),上界\(rb=1001\)。

  • 开始二分!

我们_将所有边权都_\(-mid\),再跑一边SPFA,看看现在的图中是否有正环,若有,说明答案可以再增大,\(lb=mid\);否则,\(rb=mid\)。

  • 最后,\(mid\)即为答案,若\(mid<0\),则无解。

\[\text{MainCodeHere}\]

#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;

const int N=26*26+1;
const double Eps=1e-3;

vector<int> G[N];
vector<int> W[N];
char input[1001];
int m;

double dis[N];
bool in[N];
int cnt[N];

inline bool Spfa(double test)
{
    register int i;
    queue<int>Q;
    for(i=0;i<N;i++)
        dis[i]=0,in[i]=1,cnt[i]=1,Q.push(i);
    while(!Q.empty())
    {
        int now=Q.front();Q.pop();
        in[now]=0;
        if(cnt[now]>N)return 1;//有正环 
        for(i=0;i<G[now].size() ;i++)
        {
            if(dis[G[now][i]]>dis[now]-(W[now][i]-test))
            {//                  由于是正环,所以取相反数,注意边权-mid。 
                dis[G[now][i]]=dis[now]-(W[now][i]-test);
                if(!in[G[now][i]])
                {
                    Q.push(G[now][i]);
                    in[G[now][i]]=1;
                    cnt[G[now][i]]++;
                }
            }
        }
    }
    return 0;
}

inline double Binary_Search()
{
    double lb=-1,rb=1001,mid;
    while(rb-lb>Eps)
    {
        mid=(lb+rb)/2;
        if(Spfa(mid))lb=mid;//若有正环,答案小了。 
        else rb=mid;
    }
    return mid;
}

int main()
{
    while(scanf("%d",&m)!=EOF)
    {
        if(!m)return 0;
        register int i;
        for(i=0;i<N;i++)
        {
            G[i].clear();
            W[i].clear();
        }
        for(i=1;i<=m;i++)
        {
            scanf("%s",input);
            int len=strlen(input);
            if(len<2)continue;
            int u=(input[0]-'a')*26+input[1]-'a';
            int v=(input[len-2]-'a')*26+input[len-1]-'a';
            //注意此处要-'a'。 
            G[u].push_back(v);
            W[u].push_back(len);
        }
        double result=Binary_Search();//二分答案 
        if(result>0)printf("%.2lf\n",result);
        else puts("No solution.");
    }
}

标签:SP2885,Word,int,double,Rings,mid,rb,lb,now
来源: https://www.cnblogs.com/-Wallace-/p/10663345.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有