BZOJ 2306 Ctsc2011 幸福路径 倍增Floyd

题目大意:给定一张有向图,每个点有权值,蚂蚁从某个节点出发,初始体力值为1,每走一条边体力值*=p,每经过一个点会获得幸福值为点权*体力值,求最大幸福值

令f[i][j][t]为从点i走到点j花2^t步的最大幸福值

那么有f[i][j][t]=max{f[i][k][t-1]+f[k][j][t-1]*p^(2^t)}

迭代多次即可得到答案的近似值

注意蚂蚁可能卡死在某个点不动,因此初始要将邻接矩阵清为-INF,然后每个点连一条边权为0的自环

此外注意下卡死时最后经过的那个点的权值会不会被统计 这里可能会挂

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 110
using namespace std;
int n,m,st;
double p,ans,a[M],f[M][M],g[M][M];
int main()
{
	int i,j,k,T,x,y;
	cin>>n>>m;
	for(i=1;i<=n;i++)
		scanf("%lf",&a[i]);
	cin>>st>>p;
	memset(f,0xc2,sizeof f);
	for(i=1;i<=n;i++)
		f[i][i]=0;
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		f[x][y]=a[y];
	}
	double temp=p;
	for(T=0;T<=70;T++,temp*=temp)
	{
		memset(g,0xc2,sizeof g);
		for(k=1;k<=n;k++)
			for(i=1;i<=n;i++)
				for(j=1;j<=n;j++)
					g[i][j]=max(g[i][j],f[i][k]+f[k][j]*temp);
		memcpy(f,g,sizeof f);
	}
	for(i=1;i<=n;i++)
		ans=max(ans,f[st][i]);
	printf("%.1lf\n",ans*p+a[st]);
	return 0;
}


你可能感兴趣的:(floyd,bzoj,BZOJ2306,倍增Floyd)