Bzoj2165 大楼

Time Limit: 40 Sec  Memory Limit: 259 MB
Submit: 779  Solved: 285
[Submit][Status][Discuss]

Description

xz是一个旅游爱好者,这次他来到了一座新的城市。城市中央有一幢高耸入云的大楼。这幢楼到底有多少层呢?据说和非负整数的个数是一样多的。xz想爬上这座大楼来观赏新城市的全景。这幢大楼的楼层从下至上用从小到大的非负整数编号。每层楼有n个房间,用1到n的正整数编号。楼层之间用电梯连接,电梯只能上行,不能下行或者同层移动。(下楼一般自行解决)电梯用(u,v,w)的形式给出,表示对于任意正整数i,有第i层的房间u到第i+w层的房间v有一部电梯。电梯只能从起点开往终点,不能中途停留。 xz想要观赏城市全景,至少需要登上第m层楼,即最终需要到达的楼层数≥m。由于乘坐电梯要缴纳高额的费用,而如果花销太大回家就没法报账了,xz希望乘坐电梯的次数最少。现在xz在第0层的1号房间,你需要求出这个最少的乘坐次数。

Input

第一行包含一个正整数T,表示数据的组数。接下来的数据分为T个部分。每个部分第一行包含两个正整数n和m,意义见题目描述。接下来n行,每行包含n个非负整数。这n行中,第i行第j个数为Wi,j,如果wi,j非零,则表示有电梯(i,j,Wi,j)。同一行各个数之间均用一个空格隔开。

Output

对于每组数据,输出一行一个正整数,最少的乘坐次数。

Sample Input

2
6 147
0 1 0 50 0 0
0 0 1 0 0 0
20 0 0 0 0 0
0 0 0 0 1 50
0 0 0 8 0 0
0 0 0 0 0 3
6 152
0 1 0 50 0 0
0 0 1 0 0 0
20 0 0 0 0 0
0 0 0 0 1 50
0 0 0 8 0 0
0 0 0 0 0 3

Sample Output

9
10
【样例说明】
第一组数据中,使用电梯的顺序为1→2→3→1→2→3→1→4→6→6;第二组数据中,使用电梯的顺序为1→2→3→1→2→3→1→4→5→4→6。第二组数据最后到达了153层,但是没有更短的路径使得恰好到达152层,因此答案为10。

HINT

 

有如下几类具有特点的数据: 1、有10%的数据所有的n=2; 2、有20%的数据m≤3000; 3、有20%的数据对于满足1≤i,j≤n的整数i和j,若wi,j≠0,则有wi,j≥1015; 4、有30%的数据所有的n=40。以上各类数据均不包含其他类数据。对于所有数据T=5,1≤n≤100,1≤m≤1018;对于满足1≤i,j≤n的整数i和j,有0≤wi,j≤1018。数据保证能够到达m层或更高的楼层。

 

Source

图论 数学 矩阵乘法

倍增floyd

f[t][i][j]表示经过2^t条边从i走到j的最大权值

倍增算出f后,从大到小累加,看最早何时从1到某点的权值和大于m

 

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 #define LL long long
 9 using namespace std;
10 const LL INF=1e18;
11 const int mxn=105;
12 LL read(){
13     LL x=0,f=1;char ch=getchar();
14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
16     return x*f;
17 }
18 int n,ed;
19 LL m;
20 struct Mat{
21     LL x[mxn][mxn];
22     friend Mat operator *(Mat a,Mat c){
23         Mat res;
24         for(int i=1;i<=n;i++){
25             for(int j=1;j<=n;j++){
26                 res.x[i][j]=-INF;
27                  for(int k=1;k<=n;k++){
28                     res.x[i][j]=max(res.x[i][j],a.x[i][k]+c.x[k][j]);
29                  }
30                 if(res.x[i][j]>m)res.x[i][j]=m;
31             }
32         }
33         return res;
34     }
35 }f[62],now,t;
36 inline bool check(Mat *a){
37     for(int i=1;i<=n;i++)
38         if(a->x[1][i]>=m)return 1;
39     return 0;
40 }
41 int main(){
42     int i,j;
43     int T=read();
44     while(T--){
45         n=read();m=read();
46         for(i=1;i<=n;i++)
47             for(j=1;j<=n;j++){
48                 f[1].x[i][j]=read();
49                 if(!f[1].x[i][j])f[1].x[i][j]=-INF;
50             }
51         ed=1;
52         for(i=2;i<62;i++){
53             f[i]=f[i-1]*f[i-1];
54             ed=i;
55             if(check(&f[i]))break;
56         }
57         t=f[1];
58         LL ans=1;
59         for(i=ed;i;i--){
60             now=t*f[i];
61             if(!check(&now)){
62                 t=now;
63                 ans+=1LL<<(i-1);
64             }
65         }
66         printf("%lld\n",ans+1);
67     }
68     return 0;
69 }

 

posted @ 2017-03-22 09:21  SilverNebula  阅读(378)  评论(0编辑  收藏  举报
AmazingCounters.com