题目描述
有向图 G有n个顶点 1, 2, …, n,点i 的权值为 w(i)。现在有一只蚂蚁,从 给定的起点 v0出发,沿着图 G 的边爬行。开始时,它的体力为 1。每爬过一条 边,它的体力都会下降为原来的 ρ 倍,其中ρ 是一个给定的小于1的正常数。而 蚂蚁爬到某个顶点时的幸福度,是它当时的体力与该点权值的乘积。
我们把蚂蚁在爬行路径上幸福度的总和记为 H。很显然,对于不同的爬行路 径,H 的值也可能不同。小 Z 对 H 值的最大可能值很感兴趣,你能帮助他计算 吗?注意,蚂蚁爬行的路径长度可能是无穷的。
输入输出格式
输入格式:
每一行中两个数之间用一个空格隔开。
输入文件第一行包含两个正整数 n, m,分别表示 G 中顶点的个数和边的条 数。
第二行包含 n个非负实数,依次表示 n个顶点权值 w(1), w(2), …, w(n)。
第三行包含一个正整数 v0,表示给定的起点。
第四行包含一个实数 ρ,表示给定的小于 1的正常数。
接下来 m行,每行两个正整数 x, y,表示<x, y>是G的一条有向边。可能有自环,但不会有重边。
输出格式:
仅包含一个实数,即 H值的最大可能值,四舍五入到小数点后一位。
输入输出样例
说明
对于 100%的数据, n ≤ 100, m ≤ 1000, ρ ≤ 1 – 10^-6, w(i) ≤ 100 (i = 1, 2, …, n)。
因为保留一位小数,且w(i)<=100
所以当$p^k$<1e-4时可无视
也就是说,当边数大于k时就可以忽略不计
k最大为:
$log_{0.999999}1e-4$约等于$10^7$
所以用倍增floyd求最大值
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 double f[26][101][101],w[101],inf=2e18,p,ans; 8 int n,m,S; 9 int main() 10 {int i,j,k,t,u,v; 11 cin>>n>>m; 12 for (i=1;i<=n;i++) 13 { 14 scanf("%lf",&w[i]); 15 } 16 cin>>S; 17 for (i=0;i<=25;i++) 18 for (j=1;j<=n;j++) 19 for (k=1;k<=n;k++) 20 f[i][j][k]=-inf; 21 for (i=1;i<=n;i++) 22 f[0][i][i]=0; 23 scanf("%lf",&p); 24 for (i=1;i<=m;i++) 25 { 26 scanf("%d%d",&u,&v); 27 f[0][u][v]=p*w[v]; 28 } 29 for (t=1;t<=25;t++) 30 { 31 for (i=1;i<=n;i++) 32 { 33 for (j=1;j<=n;j++) 34 { 35 for (k=1;k<=n;k++) 36 if (f[t-1][i][k]!=-inf&&f[t-1][k][j]!=-inf) 37 f[t][i][j]=max(f[t][i][j],f[t-1][i][k]+f[t-1][k][j]*p); 38 } 39 } 40 p=p*p; 41 } 42 ans=-inf; 43 for (i=1;i<=n;i++) 44 ans=max(ans,f[25][S][i]+w[S]); 45 printf("%.1lf ",ans); 46 }