[关闭]
@994495jj 2017-07-13T13:21:33.000000Z 字数 1695 阅读 843

Problem 1038 Function Graph(foj内网)(dp+倍增)

201707 (ACM)动态规划 (ACM)倍增


题解

代码

  1. #include<cstdio>
  2. #include<string>
  3. #include<algorithm>
  4. #include<vector>
  5. #include<queue>
  6. #include<cmath>
  7. #include<iostream>
  8. #include<cstdlib>
  9. #include<cstring>
  10. using namespace std;
  11. typedef long long ll;
  12. #define rep(i,a,b) for(int i=(a);i<(b);++i)
  13. #define mp make_pair
  14. #define pb push_back
  15. #define fi first
  16. #define se second
  17. #define sz(a) (int)a.size()
  18. const int N=100005;
  19. int n,k;
  20. int a[N],b[N],f[N][40],Min[N][40];
  21. ll sum[N][40];
  22. int main() {
  23. while(~scanf("%d%d",&n,&k)) {
  24. ///init
  25. memset(sum,0,sizeof(sum));
  26. rep(i,0,N) rep(j,0,40) Min[i][j]=1e9;
  27. ///read
  28. rep(i,1,n+1) scanf("%d",a+i),f[i][0]=a[i]+1;
  29. rep(i,1,n+1) scanf("%d",b+i),sum[i][0]=Min[i][0]=b[i];
  30. ///solve
  31. int di=2;
  32. for(int i=1;di<=k;++i,di<<=1) {
  33. rep(j,1,n+1) {
  34. f[j][i]=f[f[j][i-1]][i-1];
  35. }
  36. }
  37. di=2;
  38. for(int i=1;di<=k;++i,di<<=1) {
  39. rep(j,1,n+1) {
  40. Min[j][i]=min(Min[j][i-1],Min[f[j][i-1]][i-1]);
  41. sum[j][i]=sum[j][i-1]+sum[f[j][i-1]][i-1];
  42. }
  43. }
  44. ///print
  45. rep(i,1,n+1) {
  46. // cout<<"i="<<i<<endl;
  47. ll r1=0;
  48. int r2=1000000000;
  49. int u=i;
  50. for(int j=31;j>=0;--j) {
  51. if((k>>j)&1) {
  52. // cout<<"j==="<<j<<endl;
  53. r1=r1+sum[u][j];
  54. r2=min(r2,Min[u][j]);
  55. u=f[u][j];
  56. }
  57. }
  58. printf("%I64d %d\n",r1,r2);
  59. }
  60. }
  61. return 0;
  62. }

Problem 1038 Function Graph
Accept: 2 Submit: 5
Time Limit: 1500 mSec Memory Limit : 65536 KB
Problem Description

给定一张有向的函数图,图中的每个点只有一条出边,每条边附有权值w(i)。

现在要求对于每个点来说,走k步经过的所有的边的权值和以及权值的最小值。
Input

多组测试数据,请处理到文件结束(EOF)。

每组测试数据的第一行为n,k(1 <= n <= 100000, 1 <= k <= 1000000000),分别表示点的个数,以及步数。

第二行为序列f(0),f(1),...,f(n-1),表示i->f(i)的有向边,0 <= f(i) <= n - 1。

第三行为序列w(0),w(1),...,w(n-1),表示i->f(i)的权值,|w(i)| <= 1000000000。

点的编号为0到n-1。
Output

对于每组测试数据,输出n行,每行表示点i走k步的权值和以及权值最小值。
Sample Input
7 3
1 2 3 4 3 2 6
6 3 1 4 2 2 3
4 4
0 1 2 3
0 1 2 3
5 3
1 2 3 4 0
4 1 2 14 3
Sample Output
10 1
8 1
7 1
10 2
8 2
7 1
9 3
0 0
4 1
8 2
12 3
7 1
17 1
19 2
21 3
8 1
Hint

对于第一组测试据,点0走3步的路径为0->1->2->3,权值为6,3,1,权值和为10,最小值是1。
Source
2017暑期选拔赛第二场

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注