【NOIP2014八校联考第2场第2试9.28】单词接龙

Description

Bsny从字典挑出N个单词,并设计了接龙游戏,只要一个单词的最后两个字母和另一个单词的前两个字母相同,那么这两个单词就可以有序的连接起来。
Bsny想要知道在所给的所有单词中能否按照上述方式接龙组成一个单词环(可能是多个),若能,求所有环的环中单词平均长度最大值。

Solution

比赛的时候就想到了正解,但是没有时间去打。
首先把两个字母组成的东西变成26*26个点,然后一个单词就是前面的点向后面的点连边。
然后要求平均数,那么就二分答案mid。
用所有的边减去mid,然后判断一下是否存在正环就可以了。
判断是否存在正环用spfa来判断就可以了。
还有一种特殊情况,就因为不能自己练自己,但是想aaaaaaaaa,aaaa这样的东西是可以连在一起的,所以还要特殊判断一下。

Code

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
const int maxn=1e6+7;
int i,j,k,t,n,m;
int first[maxn*5],next[maxn*5],last[maxn*5],num,a[maxn],b[maxn],c[maxn],map[1000][1000],mm;
double ans,l,r,mid,chang[maxn*5],d[maxn];
int data[maxn];
char s[1007],ch;
bool bz[1000],az[1000],dz[1000];
int cz[maxn];
void add(int x,int y,int z){
    last[++num]=y,next[num]=first[x],first[x]=num;chang[num]=z;
}
bool spfa(int x){
    int head=0,tail=1,now,i;
    fo(i,0,m)d[i]=-999999999999,bz[i]=0;
    bz[x]=1;
    d[x]=0;data[1]=x;
    while(head
        now=data[++head];
        az[now]=1;
        rep(i,now){
            if(d[now]+chang[i]>d[last[i]]){
                d[last[i]]=d[now]+chang[i];
                if(!bz[last[i]]){
                    bz[last[i]]=1;
                    data[++tail]=last[i];
                    cz[last[i]]++;
                    if(cz[last[i]]>mm)return 1;
                }
            }
        }
        bz[now]=0;
    }
    return 0;
}
bool pan(int x){
    int i;
    memset(az,0,sizeof(az));
    memset(cz,0,sizeof(cz));
    fo(i,0,m){
        if(!az[i]&&dz[i]){
            if(spfa(i))return 1;
        }
    }
    return 0;
}
int main(){
    freopen("fan.in","r",stdin);
    scanf("%d",&n);
    fo(i,1,n){
        ch=getchar();m=0;
        while(ch<'a'||ch>'z')ch=getchar();
        while(ch>='a'&&ch<='z')s[++m]=ch,ch=getchar();
       // scanf("%s",s+1);m=strlen(s+1);
        a[i]=(s[1]-'a')*27+s[2]-'a'+1;
        b[i]=(s[m-1]-'a')*27+s[m]-'a'+1;
        c[i]=m;
        if(!dz[a[i]])mm++;dz[a[i]]=1;if(!dz[b[i]])mm++;dz[b[i]]=1;
        map[a[i]][b[i]]=max(map[a[i]][b[i]],c[i]);
    }
    m=27*27;
    fo(i,1,m){
        fo(j,1,m){
            if(map[i][j]){
                add(i,j,map[i][j]);
            }
        }
    }
    l=0;r=1000;
    while(r-l>0.001){
        mid=(l+r)/2;
        fo(i,1,num)chang[i]-=mid;
        if(pan(mid))l=mid;else r=mid;
        fo(i,1,num)chang[i]+=mid;
    }
    printf("%.2lf\n",l);
}

你可能感兴趣的:(noip,最短路)