jzoj100026. 【NOIP2017提高A組模擬7.7】圖(倍增)
阿新 • • 發佈:2018-12-13
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); } }