zoukankan      html  css  js  c++  java
  • 【UOJ 668】一个图的问题

    【题目描述】:

    有一个n个点n条边的有向图(每个点一条出边,可能有自环,节点编号0~N-1),每条边为,意思是i指向f(i)的边权为w(i)的边,现在小A想知道,对于每个点的si和mi。

    si:由i出发经过k条边,这k条边的权值和。

    mi:由i出发经过k条边,这k条边的权值最小值。

    【输入描述】:

    第一行两个数n和k

    第二行n个数f(i)

    第三行n个数w(i)

    【输出描述】:

    每行两个数si和mi

    【样例输入】:

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

    【样例输出】:

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

    【时间限制、数据范围及描述】:

    时间:1s 空间:512M

    30%的数据:n,k<=1000。

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

    题解:30分的暴力dfs如下(考场没想到是倍增阿巴阿巴阿巴~等我写好倍增就传代码子~

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int N=100002;
    int n,k,ans1,ans2;
    int to[N],w[N];
    void dfs(int mn,int now,int pace,int sum){
        if(pace==k) { ans1=sum; ans2=mn; return ; }
        dfs(min(w[now],mn),to[now],pace+1,sum+w[now]);
    }
    int main(){
        freopen("graph.in","r",stdin);
        freopen("graph.out","w",stdout);
        scanf("%d %d",&n,&k);
        for(int i=0;i<n;i++) { scanf("%d",&to[i]); }
        for(int i=0;i<n;i++) { scanf("%d",& w[i]); }
        for(int i=0;i<n;i++) {
            dfs(0x3f3f3f3f,i,0,0);
            printf("%d %d
    ",ans1,ans2);
        }
        return 0;
    }

     倍增就像这样阿巴阿巴~~~

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    const int N=1e5+5;
    const int M=41;
    const int oo=0x3f3f3f3f;
    int n;
    ll k;
    int to[N][M],mn[N][M];
    ll sum[N][M];
    int main(){
        scanf("%lld %lld",&n,&k);
        for(int i=0;i<n;i++) { scanf("%lld",&to[i][0]); }
        for(int i=0;i<n;i++){
            scanf("%lld",&sum[i][0]);
            mn[i][0]=sum[i][0];
        }
        for(int i=1;i<M;i++){
            for(int j=0;j<n;j++) to[j][i]=to[to[j][i-1]][i-1];
            for(int j=0;j<n;j++){
                sum[j][i]=sum[j][i-1]+sum[to[j][i-1]][i-1];
                mn[j][i]=min(mn[j][i-1],mn[to[j][i-1]][i-1]);
            }
        }
        for(int i=0;i<n;i++){
            ll s=0,kk=k;
            int m=oo,p=i;
            for (int j=M-1;j>=0;j--){
                if (!kk) break;
                if ((1ll<<j)<=kk) {
                    kk-=1ll<<j; s+=sum[p][j];
                    m=min(m,mn[p][j]); p=to[p][j];
                }
            }
            printf("%lld %d
    ",s,m);
        }
        return 0;
    }
  • 相关阅读:
    Catalyst揭秘 Day6 Physical plan解析
    Spark小课堂Week6 启动日志详解
    Spark小课堂Week5 Scala初探
    java并发再次积累
    java 2017/6/26杂记
    comparator接口与Comparable接口的区别
    ArrayList、Vector、HashMap、HashSet的默认初始容量、加载因子、扩容增量
    Java的快速失败和安全失败
    关于URL和http协议,http消息格式
    java中hashSet原理
  • 原文地址:https://www.cnblogs.com/wuhu-JJJ/p/13770389.html
Copyright © 2011-2022 走看看