[CF 702E]Analysis of Pathes in Functional Graph

来源:互联网 发布:淘宝首页html源代码 编辑:程序博客网 时间:2024/05/22 09:01

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]);}
1 0