JZOJ 100026. 【NOIP2017提高A组模拟7.7】图
生活随笔
收集整理的這篇文章主要介紹了
JZOJ 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<=10^5,k<=10^10,0<=f(i)
Hint
Solution
觀察到每個點的出邊只有一條,那說明一個點運動的路徑是固定不變的。
由于 K 的范圍太大,直接模擬是不可能的,于是我們想到倍增算法。
設 F[i][j] 表示第 i 個點、運動了 2j 個點的狀態。
開三個域 to , sum , mn 分別表示其到的點、權值和 和 最小值 。
之后倍增求出 F 數組,再每個點 O(logK) 走一遍即可 。
這樣的時間復雜度是 O(NlogK) ,可以通過本題。
Code
#include<cstdio> #include<cmath> using namespace std; const int N=100001; struct data {int to,mn;long long sum; }g[N][35]; long long k; int f[N],w[N]; long long p[35]; inline int read() {int X=0,w=1; char ch=0;while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();return X*w; } inline int min(int x,int y) {return x<y?x:y; } int main() {int n=read();scanf("%lld",&k);int t=log2(k);for(int i=p[0]=1;i<=t;i++) p[i]=p[i-1]*2;for(int i=0;i<n;i++) g[i][0].to=f[i]=read();for(int i=0;i<n;i++) g[i][0].sum=g[i][0].mn=w[i]=read();for(int j=1;j<=t;j++)for(int i=0;i<n;i++){g[i][j].to=g[g[i][j-1].to][j-1].to;g[i][j].sum=g[i][j-1].sum+g[g[i][j-1].to][j-1].sum;g[i][j].mn=min(g[i][j-1].mn,g[g[i][j-1].to][j-1].mn);}for(int i=0;i<n;i++){long long s=0,x=k;int m=1e8,pos=i;for(int j=t;j>=0 && x;j--)if(x>=p[j]){x-=p[j];m=min(m,g[pos][j].mn);s+=g[pos][j].sum;pos=g[pos][j].to;}printf("%lld %d\n",s,m);}return 0; }總結
以上是生活随笔為你收集整理的JZOJ 100026. 【NOIP2017提高A组模拟7.7】图的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 100024. 【NOIP20
- 下一篇: JZOJ 100030. 【NOIP20