大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
我们有 n 个字符串,每个字符串都是由 a∼z 的小写英文字母组成的。
如果字符串 A 的结尾两个字符刚好与字符串 B 的开头两个字符相匹配,那么我们称 A 与 B 能够相连(注意:A 能与 B 相连不代表 B 能与 A 相连)。
我们希望从给定的字符串中找出一些,使得它们首尾相连形成一个环串(一个串首尾相连也算),我们想要使这个环串的平均长度最大。
如下例:
ababc
bckjaca
caahoynaab
第一个串能与第二个串相连,第二个串能与第三个串相连,第三个串能与第一个串相连,我们按照此顺序相连,便形成了一个环串,长度为 5+7+10=22(重复部分算两次),总共使用了 3 个串,所以平均长度是 223≈7.33。
输入格式
本题有多组数据。
每组数据的第一行,一个整数 n,表示字符串数量;
接下来 n 行,每行一个长度小于等于 1000 的字符串。
读入以 n=0 结束。
输出格式
若不存在环串,输出”No solution”,否则输出最长的环串的平均长度。
只要答案与标准答案的差不超过 0.01,就视为答案正确。
数据范围
1≤n≤105
输入样例:
3
intercommunicational
alkylbenzenesulfonate
tetraiodophenolphthalein
0
输出样例:
21.66
题解
0/1分数规划,spfa求负环
#include<bits/stdc++.h>
using namespace std;
const int N = 7e2 + 10;
const int M = 2e5 + 10;
const double eps = 1e-6;
map<string,int>mm;
int ctx;
struct Edge{
int v,next,w;
}edge[M];
int head[N],cnt;
void add(int u,int v,int w){
edge[cnt].v = v;
edge[cnt].w = w;
edge[cnt].next = head[u];
head[u] = cnt ++;
}
int q[N],hh = 0,tt = 0;
double dist[N];
int num[N],vis[N];
int n;
bool check(double mid){
memset(vis,0,sizeof vis);
memset(num,0,sizeof num);
hh = tt = 0;
for(int i = 0;i < ctx;i ++){
vis[i] = true;
q[tt ++] = i;
}
int count = 0;
while(hh != tt){
int t = q[hh ++];
if(hh == N)hh = 0;
vis[t] = false;
for(int i = head[t];~i;i =edge[i].next){
int v = edge[i].v;
double w = edge[i].w - mid;
if(dist[v] < dist[t] + w){
dist[v] = dist[t] + w;
num[v] = num[t] + 1;
if(++ count > 2 * n)return true; //trick当总的更新次数大于 2 * 边数的时候
if(num[v] >= ctx)return true;
if(!vis[v]){
vis[v] = true;
q[tt ++] = v;
if(tt == N)tt = 0;
}
}
}
}
return false;
}
int main(){
while(cin>>n,n){
string word;
ctx = 0;
mm.clear();
memset(head,-1,sizeof head);
for(int i = 0;i < n;i ++){
cin>>word;
int len = word.size();
string start = word.substr(0,2);
string end = word.substr(word.size() - 2);
if(!mm.count(start))mm[start] = ctx ++;
if(!mm.count(end))mm[end] = ctx ++;
int a = mm[start],b = mm[end];
add(a,b,len);
}
double l = 0.0,r = 1000.0;
while(r - l > eps){
double mid = (l + r) / 2;
if(check(mid))l = mid;
else r = mid;
}
if(abs(l - 0) < eps)cout<<"No solution"<<endl;
else printf("%.2lf\n",r);
}
return 0;
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/168623.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...