题解 P8017 [COCI2013-2014#4] UTRKA
洛谷。
题意
这个原题描述应该足够理解。
分析
首先可以把
这有点像我们的定长路径的最短路,那么我们用矩阵来维护我们的某个点开始的
先从暴力打起,确定我们的起点,再枚举路径数,看看此时到自己的最长路径长度是否大于
inline void solve(int st) { ans=<%1,n%>; for(int i=1; i<=n; ++i) ans.a[1][i]=-INF; ans.a[1][st]=0; for(int i=1; i<=t; ++i) {//小优化,初始值为 m ans=ans*bas; if(ans.a[1][st]>0) { if(t>i) t=i,res=ans.a[1][st]; if(t==i) res=max(res,ans.a[1][st]); return; } } }
就是这样简单的思路,我们就先拿下了
时间复杂度:
接下来有两种优化方向,我们都需要运用。
- 优化枚举起点,这里占据了
的时间复杂度。 - 优化取得答案,这里占据了
的时间复杂度。
优化第一个。
我们其实并不需要枚举起点,每个起点他们的所乘
在起始时,我们将所有的
显然是没有的,应为我们要求的是最长路径长度,我们多走一条长度为
可以再次拿下一个点。
优化第二个。
在不优化第一个的前提下,我们同样也是可以优化的。
就像我们的第一个优化,给
再其基础上,我们可以发现,我们第一个优化后,也是满足二分性质的。
但是还可以更进一步,因为我们二分后是有一个快速幂操作的,快速幂本质上其实与倍增无异,我们单用倍增优化掉这一个二分。
时间复杂度:
这个时间复杂度其实已经足够度过这道题了,但是我们可以更快一点点。
分析一下答案的范围,我们答案的范围是多少,之前我们用最短路的一个最值,也就是我们的边数,但是我们的答案范围其实只有
为什么呢,假如说大于了
时间复杂度:
n=read(),m=read(); bas=<%n,n%>; for(int i=1; i<=n; ++i) for(int j=1; j<=n; ++j) bas.a[i][j]=-INF; for(int i=1; i<=n; ++i) bas.a[i][i]=0; for(int i=1; i<=m; ++i) { int u=read(),v=read(),mm=read(),ss=read(); bas.a[u][v]=max(ss-mm,bas.a[u][v]); } pw[0]=bas; for(int i=1; i<=M; ++i) pw[i]=pw[i-1]*pw[i-1]; ans=bas; int tot=1; for(int i=M; ~i; --i) { MAT res=ans*pw[i]; if(!res.check()) tot+=(1<<i),ans=res; } ++tot,ans=ans*bas; cout<<tot<<" "<<ans.get();//get:获取最大值 return 0;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!