题目大意

给你一个 \(n\) 个点,\(m\) 条边的有向图,每条边有一个权值 \(w_i\) ,每个节点有一个权值 \(a_i\) 。

你从节点 \(1\) 出发,每经过一个节点就可以获得该点的权值 \(a_i\) (起始点也可以获得,每个节点可以重复获得),问你经过的边权和恰好为 \(T\) 时,能获得的最大(点)权值和。

同时,题目还给出 \(k\) 个特殊条件,如果你在到达第 \(x_i\) 个节点时经过的边权和恰好为 \(t_i\) ,那么你就可以额外获得 \(y_i\) 的权值。

题解

我们可以观察题目数据范围:

对于所有测试点:

\(1≤n≤50\),\(n \leq m \leq 501\),\(0 \leq k \leq 200\),\(1 \leq t_i \leq T \leq 10^9\)。

\(1\leq wi \leq 5\),\(1 \leq c_i \leq 52501\),\(1 \leq u_i, v_i, x_i \leq n\),\(1 \leq y_i \leq 10^9\)。

发现每条边的边权不超过 \(5\) ,又考虑到我们需要恰好经过的边权为 \(T\) ,所以我们可以通过将边拆成点,同时建一个 \(floyd\) 矩阵,我们就可以利用矩阵快速幂来解决这个问题了。

但是我们发现还有一些特殊情况需要处理,我们可以考虑分段,每一段中间用矩阵快速幂,每一个相应的特殊情况给对应的位置添加值。

这样的复杂度是 $ O(125n^3k~logT)$ ,肯定是不行的,所以我们考虑优化。

由于我们每一次乘上的矩阵都是一样的,所以我们考虑预处理 \(2^k\) 的矩阵幂,然后每一个段都用类似于倍增的方式去处理。

这样的复杂度是 \(O(25~n^2~k~logT+125~n^3~logT)\) ,是可以接受的。

以上。

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=55,M=505,K=205;
int n,m,t,k;
int u,v,w;
int a[N],ksm[35];
struct Matrix
{
int n,m;
int h[N*5][N*5];
Matrix() {n=m=0,memset(h,-1,sizeof(h));}
void print()
{
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
printf("%lld ",h[i][j]);
printf("\n");
}
printf("\n");
}
}res[35],sta;
Matrix operator*(const Matrix a,const Matrix b)
{
Matrix ans;
ans.n=a.n,ans.m=b.m;
for(int i=1;i<=ans.n;++i)
{
for(int j=1;j<=ans.m;++j)
{
for(int k=1;k<=a.m;++k)
{
if(a.h[i][k]>=0&&b.h[k][j]>=0)
ans.h[i][j]=max(ans.h[i][j],a.h[i][k]+b.h[k][j]);
}
}
}
return ans;
}
struct Festival {int t,x,y;}s[K];
bool cmp(Festival a,Festival b) {return a.t<b.t;};
signed main()
{
// freopen("delicacy.in","r",stdin);
// freopen("delicacy.out","w",stdout);
cin>>n>>m>>t>>k;
for(int i=1;i<=n;++i)
scanf("%lld",&a[i]);
res[0].n=res[0].m=n*5;
for(int i=1;i<=n*5;++i)
{
if(i/5==(i-1)/5)
res[0].h[i][i+1]=0;
}
for(int i=1;i<=m;++i)
scanf("%lld%lld%lld",&u,&v,&w),
res[0].h[(u-1)*5+w][(v-1)*5+1]=a[v];
for(int i=1;i<=32;++i)
res[i]=res[i-1]*res[i-1];
sta.n=1,sta.m=n*5;
sta.h[1][1]=a[1];
for(int i=1;i<=k;++i)
scanf("%lld%lld%lld",&s[i].t,&s[i].x,&s[i].y);
sort(s+1,s+1+k,cmp);
ksm[0]=1;
for(int i=1;i<=32;++i)
ksm[i]=(ksm[i-1]<<1);
int tmp=0;
for(int i=1;i<=k;++i)
{
for(int j=32;j>=0;--j)
{
if(tmp+ksm[j]<=s[i].t)
tmp+=ksm[j],sta=sta*res[j];
}
if(sta.h[1][(s[i].x-1)*5+1]>=0)
sta.h[1][(s[i].x-1)*5+1]+=s[i].y;
}
for(int i=32;i>=0;--i)
{
if(tmp+ksm[i]<=t)
tmp+=ksm[i],sta=sta*res[i];
}
printf("%lld\n",sta.h[1][1]);
return 0;
}

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

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

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

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

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

  3. [NOI2020]美食家 题解

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

  4. [NOI2020] 美食家

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

  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. BZOJ 1691: [Usaco2007 Dec]挑剔的美食家 [treap 贪心]

    1691: [Usaco2007 Dec]挑剔的美食家 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 786  Solved: 391[Submit][S ...

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

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

  9. BZOJ 1691: [Usaco2007 Dec]挑剔的美食家( 平衡树 )

    按鲜嫩程度排个序, 从大到小处理, 用平衡树维护价值 ---------------------------------------------------------------------- #i ...

随机推荐

  1. Socket shutdown close简要分析

    shutdown 系统调用关闭连接的读数据通道  写数据通道 或者 读写数据通道: 关闭读通道:丢弃socket fd 读数据以及调用shutdown 后到达的数据: 关闭写通道:不同协议处理不同:t ...

  2. [LeetCode题解]143. 重排链表 | 快慢指针 + 反转

    解题思路 找到右边链表,再反转右边链表,然后按左.右逐一合并 代码 /** * Definition for singly-linked list. * public class ListNode { ...

  3. RedisUtils工具类

    package test.util; import org.springframework.beans.factory.annotation.Autowired; import org.springf ...

  4. elasticsearch快速安装启动

    准备 docker docker内安装centos容器,模拟服务器环境 centos容器安装 下载centos容器 docker pull centos 启动docker容器 docker run - ...

  5. CSRF和XSS的区别

    XSS是啥? xss就是跨域脚本攻击 什么是跨域脚本攻击? 就是在正常的输入框中(如:用户名修改等)插入script恶意代码,从而在你遍历数据的时候加载该js文件, 获取你的cookie或sessio ...

  6. RSA脚本环境配置-攻防世界-OldDriver

    [Crypto] 题目链接 [RSA算法解密] 审题分析 首先拿到一个压缩包,解压得到文件enc.txt. 先不用去管其他,第一眼enc马上联想到 RSA解密.接着往下看 [{"c" ...

  7. ERP应收应付进阶操作与子流程--开源软件诞生29

    赤龙ERP应收应付进阶讲解--第29篇 用日志记录"开源软件"的诞生 [进入地址 点亮星星]----祈盼着一个鼓励 博主开源地址: 码云:https://gitee.com/red ...

  8. 如何用Vegas完成视频编辑中的自动跟踪换图

    Vegas作为一款专业的视频剪辑软件,剪辑速度快捷,拥有各种实用工具和特效,同样也可以为用户实现视频换图的需求.今天小编就为大家讲解,如何利用Vegas自动跟踪进行换图,让视频能够更加便捷的呈现. 本 ...

  9. python测试代码

    前言: 编写函数或者类时,需要编写测试代码,来保证其的功能运行是否按预期的那样工作.在程序添加新的代码时,用来测试是否会破坏本身的功能. 我们使用python自带的unittest模块来测试代码. 编 ...

  10. Contest 984

    A 先手取最大,后手取最小,答案就是第 \(\left\lceil\frac{n}{2}\right\rceil\) 小的数. 用 nth_element 可以做到 \(O\left(n\right) ...