传送门

题意:给出n个字符串,如果一个字符串的最后两个字母和另一个(或它自身)的前两个字母相同,就可以将它们连接起来,最后可能会形成环。求环的平均字符串长度的最大值。

思路:可以把两个字母看成一个点,则最多26^2个点,一个字符串相当于一条权值为它的长度的有向边,建图。枚举答案,将每条边的权值减去这个数,然后SPFA查找图中是否还有正环,二分答案。

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

const int MAXN=705;
const double INF=0x3f3f3f3f;
const double eps=1e-3;
int n,m;
bool ff;
char s[10005];
double tt;
struct edge
{
    int v;
    double cost;
    edge(int _v=0,double _cost=0):v(_v),cost(_cost) {}
};
vector<edge>g[MAXN];
void addedge(int u,int v,double w)
{
    g[u].push_back(edge(v,w));
}
bool vis[MAXN];
int cnt[MAXN];
double dist[MAXN];
bool SPFA()
{
    queue<int>que;
    while(!que.empty())que.pop();
    for(int i=0; i<=675; i++)
    {
        vis[i]=false;
        dist[i]=0;
        cnt[i]=1;
        que.push(i);
    }
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        vis[u]=false;
        for(int i=0; i<g[u].size(); i++)
        {
            int v=g[u][i].v;
            if(dist[v]<dist[u]+g[u][i].cost-tt)
            {
                dist[v]=dist[u]+g[u][i].cost-tt;
                if(!vis[v])
                {
                    cnt[v]++;
                    //cnt[v]=cnt[u]+1;
                    if(cnt[v]>675)return true;
                    vis[v]=true;
                    que.push(v);
                }
            }
        }
    }
    return false;
}
bool judge(double t)
{
    tt=t;
    bool flag=false;
    flag=SPFA();
    if (flag)
        ff=true;
    return flag;
}
double erf(double l,double r)
{
    double mid=(l+r)/2;
    if (r-l<eps)
        return l;
    if (judge(mid))
        return erf(mid,r);
    else
        return erf(l,mid);
}
int main()
{
    while (~scanf("%d",&n))
    {
        if (n==0)
            break;
        for (int i=0;i<=675;i++)
            g[i].clear();
        int mm=-1;
        for (int i=0;i<n;i++)
        {
            scanf("%s",s);
            int l=strlen(s);
            int a=(s[l-2]-'a')*26+(s[l-1]-'a');
            int b=(s[0]-'a')*26+s[1]-'a';
            mm=max(mm,l);
            addedge(a,b,l);
        }
        ff=false;
        double ans=erf(2,mm);
        if (ff)
            printf("%.2f\n",ans);
        else
            printf("No solution.\n");
    }
    return 0;
}
Latest posts by 青鸟千秋 (see all)

CF-1025D Recovering BST(区间dp)

传送门 题意:给定n个整数,问是否能生成一棵BST(二分查找树,左子树都比它小,右子树都比它大),并且有边相连的点权的gcd>1。 思路:区间dp,dp[l][...

阅读全文

牛客网暑期多校第五场E room(费用流)

传送门 题意:有n个宿舍,每个宿舍住4个人,给定去年n个宿舍的人员构成,今年n个4人组合的情况,求最少几个人需要搬寝室。 思路:转化为最小费用最大流解...

阅读全文

HDU-4091 Zombie’s Treasure Chest(暴力)

传送门 题意:有一个容量为n的箱子,和无限多的两种珠宝,体积和价值分别是s1,v1,s2,v2,求能装下的最大价值。 思路:直接暴力枚举会TLE,先计算s1 s2的LC...

阅读全文

欢迎留言