zoukankan      html  css  js  c++  java
  • [JZOJ100026]【NOIP2017提高A组模拟7.7】图

    Description

    有一个n个点n条边的有向图,每条边为<i,f(i),w(i)>,意思是i指向f(i)的边权为w(i)的边,现在小A想知道,对于每个点的si和mi。
    si:由i出发经过k条边,这k条边的权值和。
    mi:由i出发经过k条边,这k条边的权值最小值。
     

    Input

    第一行两个数n和k
    第二行n个数f(i)
    第三行n个数w(i)

    Output

    每行两个数si和mi

    Sample Input

    7 3
    1 2 3 4 3 2 6
    6 3 1 4 2 2 3

    Sample Output

    10 1
    8 1
    7 1
    10 2
    8 2
    7 1
    9 3

    Data Constraint

    30%的数据:n,k<=1000。
    100%的数据:N<=10^5,k<=10^10,0<=f(i)<n,w(i)<=10^8。

    Hint


    十分裸的倍增题...之前没看到节点从0开始标号...傻了。

    $nxt[i][k]$表示节点$i$跳$2^j$步到达的节点,$mn[i][j]$表示...之间路长度的最小值,$sum[i][j]$表示...的路径长度和。

    水。


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    using namespace std;
    #define reg register
    #define int long long
    inline char gc() {
        static const int BS = 1 << 22;
        static unsigned char buf[BS], *st, *ed;
        if (st == ed) ed = buf + fread(st = buf, 1, BS, stdin);
        return st == ed ? EOF : *st++;
    }
    #define gc getchar
    inline int read() {
        int res = 0;char ch=gc();bool fu=0;
        while(!isdigit(ch))fu|=(ch=='-'),ch=gc();
        while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=gc();
        return fu?-res:res;
    }
    
    int n, k;
    int nxt[100005][40], mn[100005][40], sum[100005][40];
    
    signed main()
    {
        n = read(), k = read();
        for (reg int i = 1 ; i <= n ; i ++)
            nxt[i][0] = read() + 1;
        for (reg int i = 1 ; i <= n ; i ++)
            sum[i][0] = mn[i][0] = read();
        for (reg int j = 1 ; j <= 35 ; j ++)
            for (reg int i = 1 ; i <= n ; i ++)
                nxt[i][j] = nxt[nxt[i][j - 1]][j - 1];
        for (reg int j = 1 ; j <= 35 ; j ++)
            for (reg int i = 1 ; i <= n ; i ++)
                mn[i][j] = min(mn[i][j - 1], mn[nxt[i][j - 1]][j - 1]);
        for (reg int j = 1 ; j <= 35 ; j ++)
            for (reg int i = 1 ; i <= n ; i ++)
                sum[i][j] = sum[i][j - 1] + sum[nxt[i][j - 1]][j - 1];
        for (reg int i = 1 ; i <= n ; i ++)
        {
            int ans1 = 0, ans2 = 1ll << 62;
            int now = i;
            for (reg int j = 35 ; j >= 0 ; j --)
            {
                if (k & (1ll << j)) {
                    ans1 += sum[now][j];
                    ans2 = min(ans2, mn[now][j]);
                    now = nxt[now][j];
                }
            }
            printf("%lld %lld
    ", ans1, ans2);
        }
        return 0;
    }
  • 相关阅读:
    C#面向对象的三大特性概述
    SQL Server 低版本还原高版本的数据库
    将表转化成脚本的存储过程
    iis安装失败解决方法
    kafka consumer 配置详解
    C#解析XML文件
    blat
    REST接口POST方法发送文件到服务器(C#)
    http://www.codeproject.com/Questions/117324/uploadfileincwithHttpWebRequest
    PDF Password Remover
  • 原文地址:https://www.cnblogs.com/BriMon/p/9748999.html
Copyright © 2011-2022 走看看