[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;
}


posted @ 2018-10-17 22:40  Rye_Catcher  阅读(157)  评论(0编辑  收藏  举报