题目大意

给你一个 \(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. 有名管道FIFO进程间数据传输实例

    紧接着上面一个博客的简单介绍,下面进行一个没有血缘关系的进程间通信的实例,实现文件拷贝传输. 有两个进程,一个主要是fifow进程:读文件Makefile内容,写入管道;另一个进程fifor:读管道内 ...

  2. 最长回文子串的Manacher算法

    对于一个比较长的字符串,O(n^2)的时间复杂度是难以接受的.Can we do better? 先来看看解法2存在的缺陷. 1) 由于回文串长度的奇偶性造成了不同性质的对称轴位置,解法2要对两种情况 ...

  3. ceph-deploy 部署加密osd异常的问题

    问题解析 问题 journal encryption with dmcrypt (Reno Rainz) 问题原文: I'm trying to setup a cluster with encryp ...

  4. Python_自动化测试_项目

    <论坛自动化测试项目> 1.自行选择合适的社区 2.功能要求 5个以上,不包含登录页 3.多手动测试   多用selenium IDE 4.生成测试报告,发送邮件 5.计划任务定时完成 6 ...

  5. python + selenium 搭建环境步骤

    介绍在windows下,selenium python的安装以及配置.1.首先要下载必要的安装工具. 下载python,我安装的python3.0版本,根据你自己的需要安装 下载setuptools ...

  6. Dockerfile中如何自动回答标准输入的问题

    前言大家在用docker build制作自己的image的時候,都会用RUN命令来执行一些操作来安装某些必须的软件. 而一些软件的安装过程中会需要用户来输入yes/no或者y/n来确定一些东西后才能进 ...

  7. 如何用ABBYY FineReader 识别表格

    ABBYY FineReader有着强大的OCR文字识别功能,不但可以将文件转换为文本文档或Word文档,也可以识别PDF文件或者图片上的表格,并且转换为Excel文件. 下面小编就使用ABBYY F ...

  8. 如何用pdfFactory新建打印机并设置属性

    今天我们来讲一讲,在pdfFactory中如何去修改PDF文件打印页面的页边距.页面大小.页面清晰度等属性参数. pdfFactory是一款Windows平台上的虚拟打印机,在没有打印机可以安装的情况 ...

  9. guitar pro系列教程(二十):Guitar Pro使用技巧之使用向导

    本章节将采用图文结合的方式为大家讲述{cms_selflink page='index' text='Guitar Pro'}使用技巧里面的使用向导的相关知识,有兴趣的朋友可以一起来学习哦. 当你创建 ...

  10. Lambda表达式(一)入门认识篇

    Lambda表达式(一)入门认识篇 Lambda简介 Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极 ...