(1)思路:
将单词的前两个,后两个的单词视为点,将单词的长度视为边长,建立一个有向图,
然后深搜求出有向图的环的长度。
由于有向图的平均长度未知,可以将一下公式化简一下:
(E1+E2+E3+E4+……+Ek)/k = ave;
(E1+E2+E3+E4+……+Ek) = ave*k;
(E1-ave*k)+(E2-ave*k)+(E3-ave*k)+……+(Ek-ave*k)=0;
可以用二分枚举ave*k这个值,然后求出这个值的具体值。
(2)代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2e5+10;
int head[maxn],vis[maxn],n,m,tot,tt,mp[1200];
double dis[maxn];
char ss[1200];
struct Node{
int v,nxt;
double w;
}cur[maxn<<2];
void Init(){
memset(head,-1,sizeof(head));
tot = 0;tt = 0;
}
void Add(int x,int y,double z){
cur[tot].v = y;
cur[tot].nxt = head[x];
cur[tot].w = z;
head[x] = tot++;
}
int ID(int x){
if(!mp[x]){
mp[x] = ++tt;
}
return mp[x];
}
bool dfs(int x,double w){
vis[x] = 1;
for(int i=head[x];i!=-1;i=cur[i].nxt){
int y = cur[i].v;
if(dis[x]+cur[i].w-w>dis[y]){
dis[y] = dis[x]+cur[i].w-w;
if(vis[y]||dfs(y,w)){
vis[y] = 0;
return true;
}
}
}
vis[x] = 0;
return false;
}
bool spfa(double w){
for(int i=1;i<=tt;i++) dis[i] = 0;
for(int i=1;i<=tt;i++)
if(dfs(i,w)==true) return true;
return false;
}
int main(void){
while(~scanf("%d",&m)&&m){
Init();
memset(vis,0,sizeof(vis));
memset(mp,0,sizeof(mp));
for(int i=0;i<m;i++){
scanf("%s",ss);
int len = strlen(ss);
int x = (ss[0]-'a')*26+(ss[1]-'a');
int y = (ss[len-2]-'a')*26+(ss[len-1]-'a');
Add(ID(x),ID(y),1.0*len);
}
double l = 0,r = 1000.0;
int fg = 0;
while(r-l>=0.00001){
double mid = (r+l)/2.0;
if(spfa(mid)==true){
fg = 1;l = mid;
}
else r = mid;
}
if(fg==0) printf("No solution.\n");
else printf("%.2lf\n",l);
}
return 0;
}