【UOJ 668】一個圖的問題
阿新 • • 發佈:2020-10-05
【題目描述】:
有一個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 longlong 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\n",ans1,ans2); } return 0; }