Gym102222F Moving On(Floyd)
floyd好题,这个题加深了floyd真实原理的理解。学了floyd之后,一般都是用滚动数组优化过的式子去用,很多时候都忘记了floyd的本质
本题暴力dij最坏复杂度在2e9左右,跑不过时限,显然出题人肯定是设计了数据,因为他的本意是考察floyd
其实我们刚看到n的数据的时候,就会去思考floyd,之后跑偏的原因是,加了一个限制,好像floyd没法做
其实不然,因为floyd本身是三维数组,表示用前i个点能到的最短距离,这样我们只需要按给定的值排序,就能找到限制之前的最短路径
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=5e5+10; int a[N]; int h[N],ne[N],e[N],w[N],idx; int lim; int vis[N]; int dis[210][210][210]; struct node{ int x,id; }s[N]; bool cmp(node a,node b){ return a.x<b.x; } int main(){ ios::sync_with_stdio(false); int t; cin>>t; int cas=0; while(t--){ int n,q; cin>>n>>q; int i,j; for(i=1;i<=n;i++){ cin>>s[i].x; s[i].id=i; } for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ cin>>dis[0][i][j];//不用判断,题目的意思是不穿过,这里直接到了 } } sort(s+1,s+1+n,cmp); for(int k=1;k<=n;k++){ for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ dis[k][i][j]=dis[k-1][i][j]; dis[k][i][j]=min(dis[k][i][j],dis[k-1][i][s[k].id]+dis[k-1][s[k].id][j]); } } } cout<<"Case #"<<++cas<<":"<<endl; while(q--){ int x,y; cin>>x>>y>>lim; int ans=0x3f3f3f3f3f; for(i=0;i<=n;i++){ if(s[i].x>lim) break; ans=min(ans,dis[i][x][y]); } cout<<ans<<endl; } } }
没有人不辛苦,只有人不喊疼