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;
        }
    }
}
View Code

 

posted @ 2020-12-12 09:09  朝暮不思  阅读(76)  评论(0编辑  收藏  举报