题意分析

给出一个带权有向图,要求从节点 $1$ 出发,经过恰好 $T$ 的边权和,回到节点 $1$ ,求可经过的最大点权和。特别地,经过的边权和达到部分特殊数时,会有某个点的点权发生改变。

思路分析

朴素算法
  • 时间复杂度: $O(mT)$
  • 理论得分: $40pts$

设 $f_{i,j}$ 表示在节点 $j$ ,经过的边权和为 $i$ 时可经过的最大点权和。很容易可以得出 DP 方程:

$$f_{i,j}=\max_{(x,j)\in E}(f_{i-val(x,j),x})+c_j$$

暴力转移,点权改变的情况特判修改即可。

优化1
  • 时间复杂度: $O(125n^3k\log T)$
  • 理论得分:$75pts$

可以发现 $w$ 的数据范围很小,想到用矩阵快速幂优化。

首先拆点,令所有边边权都为 $1$ ,然后将所求的点权转化为边权:设有 $(u,v,w)\in E$ ,则可以将 $u$ 拆成 $u_0,u_1,...,u_{w-1}$ ,从 $u_{i-1}$ 向 $u_i$ 间连一条边,边权为 $0$ ,然后从 $u_{w-1}$ 向 $v$ 连一条边,边权为 $c_v$ 。

这样,问题就转化为,从节点 $1$ 出发,经过 $T$ 条边,回到节点 $1$ ,求可经过的最大边权和,即最长路。

定义一个广义矩阵乘法 $ans_{i,j}=max(a_{i,k}+b_{k,j})$ 。可以证明这个广义矩阵乘法同样满足矩阵乘法的基本运算律,如结合律。

设邻接矩阵为 $a$ ,可以很容易得出 DP 方程:

$$dp_i=dp_j*a^{i-j}$$

点权改变的情况怎么处理?只要先将时间从小到大排序,然后在相邻的时间之间转移,转移后在改变点权在邻接矩阵中的对应位置修改即可。

优化2
  • 时间复杂度: $O(125n^3\log T+25n^2k\log T)$
  • 理论得分: $100pts$

分析过后可以发现,因为要求的只是 $dp_{T_{1,1}}$ ,因此只要保留 $dp$ 矩阵的第一行即可;另外,发现在转移的时候要多次乘上邻接矩阵 $a$ 的相同次幂,因此可以先预处理出 $a$ 的 $2$ 的整数次幂。这样处理之后可以降低一维的复杂度。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #define ll long long
  6. using namespace std;
  7. const int N=300;
  8. const ll INF=0xcfcfcfcfcfcfcfcf;
  9. struct Node
  10. {
  11. ll p[N][N];
  12. }a[31];
  13. struct Fes
  14. {
  15. int t,x,y;
  16. #define t(i) b[i].t
  17. #define x(i) b[i].x
  18. #define y(i) b[i].y
  19. }b[N];
  20. int n,m,T,K;
  21. int c[N],id[N][5];
  22. ll dp[N];
  23. Node Max(Node x)
  24. {
  25. Node now;
  26. for(int i=1;i<=n;i++)
  27. for(int j=1;j<=n;j++)
  28. {
  29. now.p[i][j]=INF;
  30. for(int k=1;k<=n;k++)
  31. now.p[i][j]=max(now.p[i][j],x.p[i][k]+x.p[k][j]);
  32. }
  33. return now;
  34. }//广义矩阵乘法
  35. void Maxx(Node x)
  36. {
  37. ll now[N];
  38. for(int i=1;i<=n;i++)
  39. {
  40. now[i]=INF;
  41. for(int j=1;j<=n;j++)
  42. now[i]=max(now[i],dp[j]+x.p[j][i]);
  43. }
  44. for(int i=1;i<=n;i++)
  45. dp[i]=now[i];
  46. }//一维乘二维
  47. void pre()
  48. {
  49. for(int i=1;i<=30;i++)
  50. a[i]=Max(a[i-1]);
  51. }//预处理次幂
  52. void fastpow(int x)
  53. {
  54. for(int i=30;i>=0;i--)
  55. if(x&(1<<i))
  56. Maxx(a[i]);
  57. }//快速幂
  58. bool cmp(Fes x,Fes y)
  59. {
  60. return x.t<y.t;
  61. }
  62. int main()
  63. {
  64. scanf("%d%d%d%d",&n,&m,&T,&K);
  65. for(int i=1;i<=n;i++)
  66. scanf("%d",&c[i]),id[i][0]=i;
  67. memset(a,0xcfcf,sizeof(a));
  68. for(int i=1,u,v,w;i<=m;i++)
  69. {
  70. scanf("%d%d%d",&u,&v,&w);
  71. for(int j=1;j<w;j++)
  72. {
  73. if(!id[u][j])
  74. id[u][j]=++n;
  75. a[0].p[id[u][j-1]][id[u][j]]=0;
  76. }
  77. a[0].p[id[u][w-1]][v]=c[v];//拆点
  78. }
  79. pre();
  80. for(int i=1;i<=K;i++)
  81. scanf("%d%d%d",&t(i),&x(i),&y(i));
  82. sort(b+1,b+K+1,cmp);t(K+1)=T;
  83. memset(dp,0xcfcf,sizeof(dp));dp[1]=c[1];//初状态
  84. for(int i=1,d;i<=K+1;i++)
  85. {
  86. d=t(i)-t(i-1);
  87. fastpow(d);
  88. dp[x(i)]+=y(i);//点权改变
  89. }//在相邻的时间之间转移
  90. printf(dp[1]<0?"-1":"%lld",dp[1]);
  91. return 0;
  92. }

[NOI2020]美食家 题解的更多相关文章

  1. P6772 [NOI2020]美食家

    题目大意 给你一个 \(n\) 个点,\(m\) 条边的有向图,每条边有一个权值 \(w_i\) ,每个节点有一个权值 \(a_i\) . 你从节点 \(1\) 出发,每经过一个节点就可以获得该点的权 ...

  2. [XIN算法应用]NOI2020美食家

    XIN(\(updated 2021.6.4\)) 对于很多很多的题目,发现自己并不会之后,往往会直接冲上一个XIN队算法,然而,这样 \(\huge{\text{鲁莽}}\) 的行为只能获得 TLE ...

  3. [NOI2020] 美食家

    很好,自己会做NOI签到题了,去年只要会这题,再多打点暴力,\(Ag\)到手,希望今年\(NOI\)同步赛过\(Ag\)线吧,得有点拿得出手的成绩证明啊. 考虑\(T\)非常大,\(n\)又很小. 想 ...

  4. 洛谷 P6772 - [NOI2020]美食家(广义矩阵快速幂)

    题面传送门 题意: 有一张 \(n\) 个点 \(m\) 条边的有向图,第 \(0\) 天的时候你在 \(1\) 号城市,第 \(T\) 天的时候你要回到 \(1\) 号城市. 每条边上的边权表示从城 ...

  5. 【NOI2020】美食家(矩阵)

    Description 给定一张有向图,\(n\) 个顶点,\(m\) 条边.第 \(i\) 条边从 \(u_i\) 到 \(v_i\),走完该边的用时为 \(w_i\).每一个点有一个价值 \(c\ ...

  6. XIN队算法

    XIN队算法 注:名称由莫队算法改编而来 从luogu搬过来了... \(newly\;upd:2021.7.8\) \(newly\;upd:2021.6.6\) OI至高算法,只要XIN队算法打满 ...

  7. [BZOJ1691][Usaco2007 Dec]挑剔的美食家

    [BZOJ1691][Usaco2007 Dec]挑剔的美食家 试题描述 与很多奶牛一样,Farmer John那群养尊处优的奶牛们对食物越来越挑剔,随便拿堆草就能打发她们午饭的日子自然是一去不返了. ...

  8. bzoj usaco 金组水题题解(1)

    UPD:我真不是想骗访问量TAT..一开始没注意总长度写着写着网页崩了王仓(其实中午的时候就时常开始卡了= =)....损失了2h(幸好长一点的都单独开了一篇)....吓得赶紧分成两坨....TAT. ...

  9. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

随机推荐

  1. luogu P3223 [HNOI2012]排队

    LINK:排队\ 原谅我没学过组合数学 没有高中数学基础水平... 不过凭着隔板法的应用还是可以推出来的. 首先考虑女生 发现一个排列数m! 两个女生不能相邻 那么理论上来说存在无解的情况 而这道题好 ...

  2. Hadoop学习之基础环境搭建

    期望目的 基于VMware workstation 10.0 + CentOS 7 + hadoop 3.2.0,在虚拟机上搭建一套Hadoop集群环境,总共包含4个节点,其中1个master节点.3 ...

  3. 使用VMware虚拟机建立Ubuntu与主机win7的文件共享与传输

    1.要想在虚拟机与主机之间建立共享文件夹必须先安装VMware Tools.方法见https://www.cnblogs.com/lsc666js/p/13403919.html. 2.在VMware ...

  4. AutoMapper 9.0的改造(续)

    上一篇有一个读者,有疑问,如何自动化注册Dto 我开篇,做了一个自动化注册的 public sealed class AutoInjectAttribute : Attribute { public ...

  5. Improving RGB-D SLAM in dynamic environments: A motion removal approach

    一.贡献 (1)提出一种针对RGB-D的新的运动分割算法 (2)运动分割采用矢量量化深度图像 (3)数据集测试,并建立RGB-D SLAM系统 二.Related work [1]R.K. Namde ...

  6. 19-关键字package和import

    1. package的使用1.1 使用说明: * 1.为了更好的实现项目中类的管理,提供包的概念 * 2.使用package声明类或接口所属的包,声明在源文件的首行 * 3.包,属于标识符,遵循标识符 ...

  7. SqlServer 多表连接、聚合函数、模糊查询、分组查询应用总结(回归基础)

    --exists 结合 if else 以及 where 条件来使用判断是否有数据满足条件 select * from Class where Name like '%[1-3]班' if (not ...

  8. Android线性布局和帧布局

    第二次,本牛崽十分从容,今天咱们来讲讲Android Q之布局,我遇到的问题与自己学到的,大牛不要嘲笑哈,有错误可以指出来,本牛崽看到就改了. 今天我的学长跟我们开始了布局,布局看资料说好像有5种,又 ...

  9. 比PS还好用!Python 20行代码批量抠图

    你是否曾经想将某张照片中的人物抠出来,然后拼接到其他图片上去,从而可以即使你在天涯海角,我也可以到此一游? 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在 ...

  10. 【模式识别与机器学习】——PCA主成分分析

    基本思想 其基本思想就是设法提取数据的主成分(或者说是主要信息),然后摒弃冗余信息(或次要信息),从而达到压缩的目的.本文将从更深的层次上讨论PCA的原理,以及Kernel化的PCA. 引子 首先我们 ...