jzoj100026. 【NOIP2017提高A组模拟7.7】图(倍增)

100026. 【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<=105,k<=1010,0<=f(i)<n,w(i)<=10^8。

Hint
在这里插入图片描述

分析:倍增向上跳。

代码

#include <cstdio>
#define N 100005
#define ll long long
using namespace std;

struct arr
{
	int poi,min;
	ll sum;
}f[N][40];
ll bin[40],k;
int n;

int min(int x, int y){return x<y?x:y;}

int main()
{
	scanf("%d%lld", &n, &k);
	for (int i = 0; i < n; i++)
	{
		int x;
		scanf("%d", &x);
		f[i][0].poi = x;
	}	
	for (int i = 0; i < n; i++)
	{
		int x;
		scanf("%d", &x);
		f[i][0].sum = f[i][0].min = x;
	}

	for (int j = 1; j <= 35; j++)
		for (int i = 0; i < n; i++)
		{
			f[i][j].poi = f[f[i][j - 1].poi][j - 1].poi;
			f[i][j].sum = f[f[i][j - 1].poi][j - 1].sum + f[i][j - 1].sum;
			f[i][j].min = min(f[i][j - 1].min, f[f[i][j - 1].poi][j - 1].min);
		}
	bin[0] = 1;
	for (int i = 1; i <= 35; i++) bin[i] = bin[i - 1] * 2;
	for (int i = 0; i < n; i++)
	{
		ll k1 = k;
		ll s = 0;
		int ans = 1e9;
		int p = i;
		for (int j = 35; j >= 0; j--)
			if (k1 >= bin[j] && k1)
			{
				k1-= bin[j];
				ans = min(ans, f[p][j].min);
				s += f[p][j].sum;
				p = f[p][j].poi;
			}
		printf("%lld %d\n", s, ans);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值