[SP2885]WORDRING - Word Rings

题意就不解释了。。

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

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

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

建图

我们可以把每个字符串的前两个和后两个字符作为顶点,将字符串看作边,那么最多有\(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.");
    }
}

猜你喜欢

转载自www.cnblogs.com/-Wallace-/p/10663345.html
今日推荐