[倍增][最短路-Floyd][dp]
阿新 • • 發佈:2018-03-30
輸出 有向圖 %d pan 自然 公司 ems AC 說明
題目描述
小A的工作不僅繁瑣,更有苛刻的規定,要求小A每天早上在6:00之前到達公司,否則這個月工資清零。可是小A偏偏又有賴床的壞毛病。於是為了保住自己的工資,小A買了一個十分牛B的空間跑路器,每秒鐘可以跑2^k千米(k是任意自然數)。當然,這個機器是用longint存的,所以總跑路長度不能超過maxlongint千米。小A的家到公司的路可以看做一個有向圖,小A家為點1,公司為點n,每條邊長度均為一千米。小A想每天能醒地盡量晚,所以讓你幫他算算,他最少需要幾秒才能到公司。數據保證1到n至少有一條路徑。
輸入輸出格式
輸入格式:
第一行兩個整數n,m,表示點的個數和邊的個數。
接下來m行每行兩個數字u,v,表示一條u到v的邊。
輸出格式:
一行一個數字,表示到公司的最少秒數。
輸入輸出樣例
輸入樣例#1:4 4 1 1 1 2 2 3 3 4輸出樣例#1:
1
說明
【樣例解釋】
1->1->2->3->4,總路徑長度為4千米,直接使用一次跑路器即可。
【數據範圍】
50%的數據滿足最優解路徑長度<=1000;
100%的數據滿足n<=50,m<=10000,最優解路徑長度<=maxlongint。
題解
- 這道題目求的是從1號點到n號點最少要幾秒到達
- 我們可以看到這個跑路器,每秒跑2^k條邊(每條邊1km),
- 用一個參數k表示2^k,G[i][j][k]代表從i到j是否存在一條長度為2^k的路徑
- 再用dis數組來記錄兩點之間需要用多久到達
- 這樣我們可以用G來保存所有的邊,並且進行預處理
- 然後把所有一秒能到的兩個點之間都連上邊,並把距離相應調整為1
- 那麽我們就把所有一秒能到的點之間都鋪上了邊
- 最後就要求出兩點之間的最短路,跑一遍Floyd
代碼
1 #include<bits/stdc++.h> 2 using namespace std; 3 int dis[60][60],n,m,x,y; 4 bool G[60][60][65]={false}; 5int main() 6 { 7 memset(dis,10,sizeof(dis)); 8 scanf("%d%d",&n,&m); 9 for(int i=1;i<=m;i++) 10 { 11 scanf("%d%d",&x,&y); 12 dis[x][y]=1; 13 G[x][y][0]=true; 14 } 15 for(int k=1;k<=64;k++) 16 for(int i=1;i<=n;i++) 17 for(int t=1;t<=n;t++) 18 for(int j=1;j<=n;j++) 19 if(G[i][t][k-1]&&G[t][j][k-1]) 20 { 21 G[i][j][k]=true; 22 dis[i][j]=1; 23 } 24 for(int k=1;k<=n;k++) 25 for(int i=1;i<=n;i++) 26 for(int j=1;j<=n;j++) 27 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); 28 printf("%d",dis[1][n]); 29 return 0; 30 }
[倍增][最短路-Floyd][dp]