题意:给你n个串,让你找到一系列串,这些串首尾相连(开头和结尾的两个字母相同),问最大的平均长度是多少
思路:做差分约束做到的这道题,但是很明显不是差分约束。。看起来有点像01分数规划=。=,事实证明还是有点关系的。。
///渣渣题解。。不知道的最好出门左转=。=
这道题要求一些字符串长度和的最大值,二分这个最大值,就得到一个不等式,就是 选取的字符串的长度和/n > mid,如果存在这样的串l = mid,反之。。,就这样二分,满足精度 跳出输出解,现在任务就是判断是否存在这样的环,把这个不等式变形之后:长度和>mid * n,接着变形,得到:长度减去mid的和>0,这样把边权换为减去mid的之后,判断是否有正环就好了。。
原来判负环一直都是用spfa判断进队次数,这次学了个dfs版的spfa,传说中比那个快=。=
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#include<vector>
#include<queue>
const int maxn = 1000;
const double eps = 1e-6;
int n;
struct Side{
int v,next;
double w;
}side[maxn*maxn];
int node[maxn],top;
void add_side(int u,int v,double w){
side[top] = (Side){v,node[u],w};
node[u] = top++;
}
int mm[maxn][maxn];
bool have[maxn];
double dis[maxn];
bool is[maxn];
int flag;///fu huan
void dfs(int s,double mid){
is[s] = 1;
for(int i = node[s];i != -1;i = side[i].next){
int v = side[i].v;
if(dis[v] < dis[s] + side[i].w - mid){
dis[v] = dis[s] + side[i].w -mid;
if(is[v]){
flag = 1;
return;
}
dfs(v,mid);
if(flag)return;
}
}
is[s] = 0;
}
bool judge(double mid){
for(int i = 0;i < maxn;i ++){
dis[i] = -10000;
is[i] = false;
}
flag = 0;
for(int i = 1;i < maxn;i ++){
if(have[i]){
dfs(i,mid);
if(flag)return true;
}
}
return false;
}
int main(){
//freopen("in.txt","r",stdin);
while(~scanf("%d",&n),n){
memset(node,-1,sizeof(node));
memset(mm,0,sizeof(mm));
memset(have,0,sizeof(have));
top = 0;
char s[1100];
double l = 0,r = 0,mid;
for(int i = 1;i <= n;i ++){
scanf("%s",s);
int l = strlen(s);
r = max(r,(double)l);
int tail,head;
if(l == 1)head = tail = s[0] - 'a';
else {
head = (s[0] - 'a')*30 + s[1] - 'a' + 1;
tail = (s[l-2] - 'a')*30 + s[l-1] - 'a' + 1;
}
mm[head][tail] = max(l,mm[head][tail]);
have[head] = have[tail] = 1;
}
for(int i = 0;i < maxn;i ++){
if(have[i] == 0)continue;
for(int j = 0;j < maxn;j ++){
if(have[j] == 0||mm[i][j] == 0)continue;
add_side(i,j,mm[i][j] * 1.0);
//cout<<i<<' '<<j<<' '<<mm[i][j]<<endl;
}
}
while(r - l > eps){
mid = (l + r)/2.0;//cout<<mid<<endl;
if(judge(mid))l = mid;
else r = mid;
}
if(mid < 1.0)printf("No solution.\n");
else printf("%.2f\n",mid);
}
return 0;
}