【补题日记】[2022牛客暑期多校2]L-Link with Level Editor I

本文详细分析了一道图论题目,探讨了如何利用滚动数组优化状态转移方程,特别是在处理与起点相关的问题时。作者指出,初始状态的设置不仅关乎赋值,还影响后续的状态更新。通过实例和调试,强调了正确理解状态转移方程对于求解最晚出发点的重要性。
摘要由CSDN通过智能技术生成

Pro

https://ac.nowcoder.com/acm/problem/239349

Sol

f i , j f_{i,j} fi,j表示在第i个世界到底第j个点,最晚可以从哪个世界出发。

状态转移方程:如果一个世界里存在一条x->y的边,那么 f i , y = m a x ( f i − 1 , y , f i − 1 , x ) f_{i,y}=max(f_{i-1,y},f_{i-1,x}) fi,y=max(fi1,y,fi1,x),而第一维只与上一个世界有关系,则可以使用滚动数组优化掉。

本题难理解点在于下方代码:f[(i-1)&1][1] = i;Fo(j,1,m) f[i&1][j] = f[(i-1)&1][j];f[i&1][1] = i; Fo(j,2,m) f[i&1][j] = f[(i-1)&1][j];是否等价。

为什么会这么想呢?因为很容易理解的是,第i个世界的第1号点可以由i-1个世界的第1号点得来,就误认为此处f[(i-1)&1][1] = i;仅仅是对 f i , x f_{i,x} fi,x赋初值,所以才会写出后者的代码。

而事实上通过测试样例并仔细调试可以发现,此处不仅仅与赋值有关,且与下方的更新也有关,因此此处的理解可以为:第i个世界可以作为整个关卡的开始,此时在该世界中到达1号点的最晚的世界为i。为什么不考虑以前面世界中的1号节点作为开始呢?其实已经考虑完了:

假设以前面的某个世界的1号节点作为关卡的开始,如果前面的每个世界都选择1号节点,直到选择到第i个世界的1号节点,此时不如直接选择第i个世界的号节点更优;如果前面的每个世界存在一条路径的移动,则到达第i个世界时的节点编号一定不是1,也就是在区间[2,m]里一定包含了以前面世界中的1号节点作为开始的情况。因此需要一句关键代码f[(i-1)&1][1] = i;

Code

//By cls1277
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define Fo(i,a,b) for(LL i=(a); i<=(b); i++)
#define Ro(i,b,a) for(LL i=(b); i>=(a); i--)
#define Eo(i,x,_) for(LL i=head[x]; i; i=_[i].next)
#define Ms(a,b) memset((a),(b),sizeof(a))
#define endl '\n'

// const LL maxn = ;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    #ifdef DEBUG
    freopen("data.txt","r",stdin);
    #endif
    LL n, m, ans=INT_MAX; cin>>n>>m;
    vector<vector<LL>> f(2, vector<LL>(m+1, -INT_MAX));
    Fo(i,1,n) {
        LL l; cin>>l;
	    f[(i-1)&1][1] = i;
	    Fo(j,1,m) f[i&1][j] = f[(i-1)&1][j];
//      f[i&1][1] = i;
//      Fo(j,2,m) f[i&1][j] = f[(i-1)&1][j];
        Fo(j,1,l) {
            LL x, y; cin>>x>>y;
            f[i&1][y] = max(f[i&1][y], f[(i-1)&1][x]);
            if(y==m&&f[i&1][m]!=-INT_MAX) ans = min(ans, i-f[i&1][m]+1);
        }
    }
    cout<<(ans==INT_MAX?-1:ans);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cls1277

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值