Description
Bsny从字典挑出N个单词,并设计了接龙游戏,只要一个单词的最后两个字母和另一个单词的前两个字母相同,那么这两个单词就可以有序的连接起来。
Bsny想要知道在所给的所有单词中能否按照上述方式接龙组成一个单词环(可能是多个),若能,求所有环的环中单词平均长度最大值。
Input
第一行一个整数N,表示单词数量。
接下来N行,每行一个字符串,仅包含小写字母。
Output
若能组成单词环,输出环中单词的最大平均长度,结果保留2位小数;否则输出”No solution.”(不包括双引号)。精度误差在0.01都算正确。
Sample Input
3
intercommunicational
alkylbenzenesulfonate
tetraiodophenolphthalein
Sample Output
21.67
Data Constraint
20%的数据:
n≤20
;
70%的数据:
n≤1000
;
100%的数据:
n≤100000
,每个单词长度不超过1000。输入数据比较大,C/C++的同学用scanf输入。
Solution
把问题转换一下,可以这样处理:
把一个单词的前两个单词和后两个单词视为点,单词长度视为边权
那么点数最多为 26∗26=676 个点,这样在其中找环即可
看到题目问的是最大值,那么可以二分答案 len ,每一条边权值减去 len ,
于是问题变成判定是否存在正权环!有则 len 可以更大,没有则更小。
对于判定环,可以使用 SPFA,BFS和DFS都可以,每个点跑一次最长路即可
详情请见我的博客:http://blog.csdn.net/liyizhixl/article/details/54565085
(SPFA算法及判负环方法)
注意走过的点不用再做SPFA,时间复杂度 O(NlogN)
Code
#include<cstdio>
#include<cstring>
using namespace std;
const int N=3000001,M=26*26+1;
const double E=1e-3;
int n,tot;
int node[M],que[N];
double dis[M],w[N];
int first[M],next[N],en[N];
bool bz[M],vis[M];
char s[1002];
inline int get(int x,int y)
{
return 26*(x-'a')+y-'a'+1;
}
inline void insert(int x,int y,int z)
{
next[++tot]=first[x];
first[x]=tot;
en[tot]=y;
w[tot]=z;
}
inline bool spfa(int st,double num)
{
for(int i=1;i<=node[i];i++) dis[node[i]]=0;
int l=0,r=1;
vis[que[1]=st]=true;
while(l<r)
{
int now=que[++l];
bz[now]=false;
for(int i=first[now];i;i=next[i])
if(dis[now]+w[i]-num>dis[en[i]])
{
dis[en[i]]=dis[now]+w[i]-num;
if(!bz[en[i]])
{
bz[que[++r]=en[i]]=vis[en[i]]=true;
if(r>n) return true;
}
}
}
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
int len=strlen(s+1);
if(len==1) continue;
int x=get(s[1],s[2]),y=get(s[len-1],s[len]);
if(x!=y) insert(x,y,len);
if(!vis[x]) vis[node[++node[0]]=x]=true;
if(!vis[y]) vis[node[++node[0]]=y]=true;
}
double l=0,r=1000;
while(l+E<r)
{
double mid=(l+r)/2;
for(int i=1;i<=node[0];i++) vis[node[i]]=false;
bool pd=false;
for(int i=1;i<=node[0];i++)
if(!vis[node[i]] && spfa(node[i],mid))
{
pd=true;
break;
}
if(pd) l=mid; else r=mid;
}
if(!l) printf("No solution."); else printf("%.2lf",l);
return 0;
}