2306: [Ctsc2011]幸福路径

来源:互联网 发布:腾讯上班知乎 编辑:程序博客网 时间:2024/05/29 16:58

题目链接

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

题解:直接矩阵乘法floyd,大力卡精度就能过了
根据定义
初始矩阵f[0]:恰好经过一条边
f[n-1]:恰好经过n条边

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

注意这个状态是不含有起点的贡献的,最后要加上

我的收获:23333

#include <cmath>  #include <cstdio>  #include <cstring>  #include <iostream>  #include <algorithm>  using namespace std;#define M 110int n,m,st,cnt;double p,mx,tp,g[M];struct Mat{int x;double m[M][M];Mat(){x=1,memset(m,0xfe,sizeof(m));}}w;//-INFMat operator*(Mat a,Mat b){    Mat c;c.x=a.x;    for(int i=1;i<=a.x;i++)        for(int j=1;j<=b.x;j++)            for(int k=1;k<=a.x;k++)                c.m[i][j]=max(c.m[i][j],a.m[i][k]+b.m[k][j]*tp);    return c;}Mat operator^(Mat a,long long p){    Mat c;bool flag=true;    for(;p;p>>=1,a=a*a,tp*=tp)    if(p&1) {if(flag) c=a,flag=false;else c=c*a;}    return c;}void work(){    tp=p;    for(double exa=p;exa>1e-10;exa*=exa) cnt++;    Mat ans=w^(1ll<<cnt);    for(int i=1;i<=n;i++) mx=max(mx,ans.m[st][i]);    printf("%.1lf\n",mx+g[st]);}void init(){    int x,y;    cin>>n>>m;    for(int i=1;i<=n;i++) w.m[i][i]=0;    for(int i=1;i<=n;i++) scanf("%lf",&g[i]);    cin>>st>>p;    while(m--) scanf("%d%d",&x,&y),w.m[x][y]=g[y]*p;//1条边,要乘一下    w.x=n;}int main()  {    init();    work();     return 0;  }  
原创粉丝点击