[JZOJ100026]图--倍增

[JZOJ100026]图--倍增

题目链接

太懒了,自行搜索

分析

裸倍增,不多说

\(fa[i][j]\)表示\(i\)\(2^j\)步走到的点

\(f[i][j]\)表示\(i\)\(2^j\)步经过边权之和

\(mi[i][j]\)表示\(i\)\(2^j\)步经过的边权最小值

\(fa[i][j]=fa[fa[i][j-1]][j-1]\)

\(f[i][j]=f[i][j-1]+f[fa[i][j-1]][j-1]\)

\(mi[i][j]=min(mi[i][j-1],mi[fa[i][j-1]][j-1])\)

然后一开始我\(naiive\)认为要找一个环上的点开始跳,于是打个了搜索,结果不知道怎么回事一直\(WA\),后面才学到根本不用那么麻烦...太菜了

代码

/*
  code by RyeCatcher
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <utility>
#include <queue>
#include <vector>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <iostream>
#define DEBUG freopen("dat.in","r",stdin);freopen("wa.out","w",stdout);
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define ri register int
#define ll long long
#define ull unsigned long long
#define SIZE 1<<22
using std::min;
using std::max;
using std::priority_queue;
using std::queue;
using std::vector;
using std::pair;
using namespace __gnu_pbds;
inline char gc(){
    static char buf[SIZE],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,SIZE,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
template <class T>inline void read(T &x){
    x=0;int ne=0;char c;
    while((c=gc())>'9'||c<'0')ne=c=='-';x=c-48;
    while((c=gc())>='0'&&c<='9')x=(x<<3)+(x<<1)+c-48;x=ne?-x:x;return ;
}
const int maxn=100005;
const int inf=0x7fffffff;
int LIM;
int n;
vector <int> son[maxn];
int fa[maxn][33],mi[maxn][33];
ll f[maxn][33],k;
int pos[35],tot=0,cnt=0,ms=inf;
ll ans=0;
int main(){
    int x,y;
    //FO(graph);
    freopen("wtf.out","w",stdout);
    freopen("graph4.in","r",stdin);
    read(n),read(k);
    LIM=log2(k)+1;
    for(ri i=1;i<=n;i++){
        read(x),x++;
        fa[i][0]=x,son[x].push_back(i);
    }
    for(ri i=1;i<=n;i++)read(f[i][0]),mi[i][0]=f[i][0];
    for(ri o=1;o<=LIM;o++){
        for(ri i=1;i<=n;i++){
            fa[i][o]=fa[fa[i][o-1]][o-1];
            f[i][o]=f[i][o-1]+f[fa[i][o-1]][o-1];
            mi[i][o]=min(mi[i][o-1],mi[fa[i][o-1]][o-1]);
        }
    }
    while(k){
        if(k%2)pos[++tot]=cnt;
        k=k>>1;
        cnt++;
    }
    for(ri i=1;i<=n;i++){
        ms=inf,ans=0,x=i;
        for(ri j=1;j<=tot;j++){
            ans+=f[x][pos[j]];
            ms=min(ms,mi[x][pos[j]]);
            x=fa[x][pos[j]];
        }
        printf("%lld %d\n",ans,ms);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Rye-Catcher/p/9807679.html
今日推荐