[luogu1119] 災後重建
阿新 • • 發佈:2018-09-22
algo 一次 set max urn tps scan ring return
傳送門
Solution
雖然沒做過多少Floyd的題……但是還是靈性了一波。
首先你會發現數據是有單調性的!那麽我們就幹脆一個一個點加進去跑Floyd就行了,那麽怎麽加點呢?
對於某個點key,我要把它加進去,我們可以假設它是起點,那麽以i為中點,j為終點,跑一下平方的松弛操作;同上,分別假設key為終點,key為中點。
這樣我們每加入一個點,它的循環次數跟跑一次完整的Floyd一樣了,避免了重復計算。
#include <cstdio> #include <cstring> #include <algorithm> #define MAXN 205 #define INF 100005 int Graph[MAXN][MAXN]; int vis[MAXN]; int over[MAXN]; int N,M,Q; inline void add(int key){ for(register int i=1;i<key;++i) for(register int j=1;j<key;++j){ Graph[key][j] = std::min(Graph[key][j],Graph[key][i]+Graph[i][j]); } for(register int i=1;i<key;++i) for(register int j=1;j<key;++j){ Graph[j][key] = std::min(Graph[j][key],Graph[j][i]+Graph[i][key]); } for(register int i=1;i<key;++i) for(register int j=1;j<key;++j){ Graph[i][j] = std::min(Graph[i][j],Graph[i][key]+Graph[key][j]); } } int main(){ std::memset(vis,0,sizeof(vis)); scanf("%d%d",&N,&M); for(register int i=1;i<=N;++i){ scanf("%d",&over[i]); } for(register int i=1;i<=N;++i) for(register int j=1;j<=N;++j){ Graph[i][j] = INF; } int u,v,w; for(register int i=1;i<=M;++i){ scanf("%d%d%d",&u,&v,&w); Graph[u+1][v+1] = w; Graph[v+1][u+1] = w; } int point = 0; scanf("%d",&Q); int t = 0; for(register int i=1;i<=Q;++i){ scanf("%d%d%d",&u,&v,&t); u++;v++; for(;point<N&&over[point+1]<=t;){ add(++point); vis[point] = 1; } if(vis[u]==0||vis[v]==0||Graph[u][v]==INF)puts("-1"); else printf("%d\n",Graph[u][v]); } return 0; }
[luogu1119] 災後重建