zoukankan      html  css  js  c++  java
  • 【洛谷P1119】灾后重建

    题目大意:给定一个 N 个顶点,M 条边的无向图,每个顶点有一个时间戳,且时间戳大小按照顶点下标大小依次递增,在给定时间 t 时,时间戳严格大于 t 的顶点不能被访问,现在有 Q 次询问,每次询问在给定时间下,任意两个点的最短路是多少,若有点不能被访问,则输出 -1。

    题解:因为 N<=200,且询问的是任意两点的最短路问题,所以考虑 Floyd 算法。在 Floyd 算法中,问题的阶段是经过前几个顶点,这句话也可以理解为:只经过前几个顶点的任意两点的最短路是多少。而这正好符合时间戳的概念,即:在某个阶段时,大于某一时间戳上限的点不会被访问到。因此,可以预处理出各个阶段,询问的时候直接查找询问时间所在的区间即可。时间复杂度为 (O(n^3+Qlogn))

    代码如下

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=210;
    const int inf=0x3f3f3f3f;
    
    inline int read(){
        int x=0,f=1;char ch;
        do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
        do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
        return f*x;
    }
    
    int n,m,t[maxn],d[maxn][maxn][maxn];
    
    void read_and_parse(){
        n=read(),m=read();
        for(int i=1;i<=n;i++)t[i]=read();
    
        memset(d,0x3f,sizeof(d));
        for(int i=1;i<=n;i++)d[0][i][i]=0;
        for(int i=1,x,y,z;i<=m;i++){
            x=read()+1,y=read()+1,z=read();
            d[0][x][y]=d[0][y][x]=min(d[0][x][y],z);
        }
    }
    
    void floyd(){
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    d[k][i][j]=min(d[k-1][i][j],d[k-1][i][k]+d[k-1][k][j]);
    }
    
    void solve(){
        floyd();
        int q=read();
        while(q--){
            int x=read()+1,y=read()+1,z=read();
            int idx=upper_bound(t+1,t+n+1,z)-t-1;
            printf("%d
    ",t[x]<=z&&t[y]<=z&&d[idx][x][y]!=inf?d[idx][x][y]:-1);
        }
    }
    
    int main(){
        read_and_parse();
        solve();
        return 0;
    }
    
  • 相关阅读:
    枚举类型总结
    正则表达式-Java
    java中Mongo
    cookie
    xsd解析
    水平分表的实现
    c#位运算小例子笔记
    c#设计模式之观察者模式(Observer Pattern)
    c#设计模式之代理模式(Proxy Pattern)
    .Net 数据缓存浅析
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10235344.html
Copyright © 2011-2022 走看看