[CF 702E]Analysis of Pathes in Functional Graph

本文介绍了一种使用倍增算法解决特定图上的最短路径问题的方法。在一个特殊的有向图中,每个节点恰好有一条出边,目标是从每个节点出发经过k条边后达到的节点及其边权和最小值。文章提供了完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

给出一张n个点,n条边的有向图。每个点的出度均为1,每条边有边权。
求:从每个点出发走k条边,所有方案中的边权和和最小值。
n<=10^5,k<=10^10

Solution

由于最近颓总在刷一些C、D题,今天闲着没事干随便找了道E题来刷~~
然而这道E题不是水题吗?
我才不会说我找了道通过人数三位数的E题呢
看到k这么大,肯定想到有一些神奇的log算法辣==
然后发现每个点出发,走k步走到的点是一定的,那么就倍增就好辣==
我一开始想到的类似快速幂的打法是什么鬼
哦,CF上long long类型要用I64d

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int N=1e5+5,inf=0x7fffffff;
ll mi[34],sum[N][34],ans[N],k;
int Min[N][34],to[N][34],MIN[N],n;
int main() {
    scanf("%d%I64d",&n,&k);
    mi[0]=1;fo(i,1,33) mi[i]=mi[i-1]*2;
    fo(i,1,n) MIN[i]=inf;
    fo(i,1,n) scanf("%d",&to[i][0]),to[i][0]++;
    fo(i,1,n) scanf("%I64d",&sum[i][0]),Min[i][0]=sum[i][0];
    fo(j,1,33) fo(i,1,n) {
        to[i][j]=to[to[i][j-1]][j-1];
        sum[i][j]=sum[i][j-1]+sum[to[i][j-1]][j-1];
        Min[i][j]=min(Min[i][j-1],Min[to[i][j-1]][j-1]);
    }
    fo(i,1,n) {
        ll now=0;int x=i;
        fd(j,33,0) if (now+mi[j]<=k) {
            ans[i]+=sum[x][j];
            MIN[i]=min(MIN[i],Min[x][j]);
            now+=mi[j];x=to[x][j];
        }
    }
    fo(i,1,n) printf("%I64d %d\n",ans[i],MIN[i]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值