迅雷第三季度營收 6000 萬美元同比增 37.3%,因減少廣告導致此類營收下降 29%
阿新 • • 發佈:2021-11-11
分析
通過簡單分析題目,我們知道,我們要計算的就是。
隨著不斷有點被啟用,隨之而來的邊也逐漸可用的情況下,問在某情況下的兩點之間的最小值
本題的重要程度*:提高+/省選-
需要明白Floyd演算法的本質才能很好地寫出這道題
讓我們首先從Floyd演算法談起,這看上去是一個非常簡單的程式碼,實際上它確實也非常簡潔。
for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j];
演算法本質:動態規劃,就是通過其他的點進行中轉來求的兩點之間的最短路。因為我們知道,兩點之間有多條路,如果換一條路可以縮短距離的話,就更新最短距離。而它最本質的思想,就是用其他的點進行中轉,從而達到求出最短路的目的。
返回來看程式碼,一句話概括:從i號頂點到j號頂點只經過前k號點的最短路程。
而我們再回頭看題意:
所有的邊全部給出,按照時間順序更新每一個可用的點(即修建好村莊),對於每個時間點進行兩點之間詢問,求對於目前建設的所有村莊來說任意兩點之間的最短路
不正好就是Floyd演算法中使用前k個節點更新最短路的思維嗎?
因此我們的解題思路就顯而易見了,按照時間不斷的解封新的點。
本題核心
inline void updata(int k){ for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(f[i][j]>f[i][k]+f[j][k]) f[i][j]=f[j][i]=f[i][k]+f[j][k];//用這個新的更新所有前面的 return; }
只更新到用前k個點
Ac_Code
#include<bits/stdc++.h> using namespace std; const int N = 210,INF = 0x3f3f3f3f; int a[N],g[N][N]; int n,m; void update(int idx) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) g[j][i]=min(g[j][i],g[i][idx]+g[idx][j]),g[i][j]=g[j][i]; } int main() { cin>>n>>m; for(int i=0;i<n;i++) cin>>a[i]; for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(i!=j) g[i][j]=INF; else g[i][j]=0; while(m--) { int u,v,t; cin>>u>>v>>t; g[u][v]=g[v][u]=t; } int q,idx=0; cin>>q; while(q--) { int u,v,t; cin>>u>>v>>t; while(idx<n&&a[idx]<=t) { update(idx); idx++; } if(a[u]>t||a[v]>t) puts("-1"); else { if(g[u][v]==INF) puts("-1"); else cout<<g[u][v]<<endl; } } return 0; }