[SPOJ]2885 loj10082 WORDRING - Word Rings

链接:

loj:https://loj.ac/problem/10082

luogu:https://www.luogu.com.cn/problem/SP2885

SPOJ:https://www.spoj.com/problems/WORDRING/

对于每个字符串的首尾两个长度为\(2\)的子串,哈希之后连一条权为当前字符串的长度的有向边

然后题目只需要找到边权平均值最大的正环

设正环由\(k\)条边组成,分别标号为\(1,2,…,k\),第\(i\)条边的长度为\(d_i\)

则平均值\(a=\dfrac{ \sum \limits^{k}_{i=1} d_i } {k}\)

然后\(\sum\limits^{k}_{i=1} (d_i - a) = 0\)

做上式大于\(0\),则说明有更优解

于是考虑二分答案即可做出

代码:

#include
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;++i)
inline int read()
{
    bool f=0;int x=0;char ch;
    do{ch=getchar();f|=(ch=='-');}while(!isdigit(ch));
    do{x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}while(isdigit(ch));
    return f?-x:x;
}
inline void write(int x)
{
    if(x<0)x=-x,putchar('-');
    if(x>9)write(x/10);putchar(x%10+'0');
}
inline void writesp(int x)
{
	write(x);putchar(' ');
}
inline void writeln(int x)
{
	write(x);puts("");
}
const int maxn=1e6+5; 
int head[maxn],nxt[maxn],w[maxn],to[maxn],vis[maxn],tot;
double dis[maxn];
void insert(int u,int v,int val)
{
    nxt[++tot]=head[u];
    head[u]=tot;
    w[tot]=val;
    to[tot]=v;
}
int spfa(double t,int u)
{
	vis[u]=1;
	for(int i=head[u];i;i=nxt[i])
	{
		int v=to[i],val=w[i];
		if(dis[v]>s;
			int len=s.size(),a=(s[0]-96)*100+(s[1]-96),b=(s[len-2]-96)*100+(s[len-1]-96);
			insert(a,b,len);
			sum+=len;
		}
		double l=0,r=sum,mid;
		while(l+1e-2

你可能感兴趣的:([SPOJ]2885 loj10082 WORDRING - Word Rings)