• P1119 灾后重建


    传送门

    思路:

      看到村庄的数目 ≤ 200,很显然可以用 floyd 来做。

      但如果对于每次询问时间 t 都暴力地跑一遍 floyd ,时间复杂度为 n4 ,只能拿到 50 分。

      所以,要考虑一下如何优化 。。。

      因为每个村庄的 t [ i ],及询问 ( x , y , t ) 中的 t 都是不下降的,所以可以从第一个村庄 0 开始找( k = 0 ),如果 t [ k ] > 这次询问的 t ,就相当于把这之前的任意两个村庄的最短路处理好了(或者是两个村庄不连通),直接输出 d[ x ][ y ]。不然,就 k++ ,继续把村庄 k 作为中转点,跑 floyd ,直 t [ k ] > 这次询问的 t 。( 因为所有的 t 都是有序的,所以 k 不用再重新赋为 0 ;如果时间 t 是无序的,也可以离线处理,sort 一遍,再求最短路。)

    Code:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<deque>
    #include<map>
    #include<set>
    using namespace std;
    #define lck_max(a,b) ((a)>(b)?(a):(b))
    #define lck_min(a,b) ((a)<(b)?(a):(b))
    #define INF 0x3f3f3f3f
    typedef long long LL;
    const int maxn=5e4+7;
    LL n,m,d[205][205],t[maxn];
    inline LL read()
    {
        LL kr=1,xs=0;
        char ls;
        ls=getchar();
        while(!isdigit(ls))
        {
            if(!(ls^45))
                kr=-1;
            ls=getchar();
        }
        while(isdigit(ls))
        {
            xs=(xs<<1)+(xs<<3)+(ls^48);
            ls=getchar();
        }
        return xs*kr;
    }
    inline void out(LL xs)
    {
        if(!xs) {putchar(48); return;}
        if(xs<0) putchar('-'),xs=-xs;
        int kr[57],ls=0;
        while(xs) kr[++ls]=xs%10,xs/=10;
        while(ls) putchar(kr[ls]+48),ls--;
    }
    inline void clear()
    {
        memset(d,INF,sizeof(d));
        memset(t,INF,sizeof(t));
    }
    LL x,y,z,q,k;
    int main()
    {
        n=read();m=read();
        clear();
        for(LL i=0;i<n;i++) t[i]=read(),d[i][i]=0; 
        for(LL i=1;i<=m;i++)
        {
            x=read();y=read();z=read();d[x][y]=d[y][x]=z;
        }
        q=read();
        while(q--)
        {
            x=read();y=read();z=read();
            while(t[k]<=z)
            {
                for(LL i=0;i<n;i++)
                    for(LL j=0;j<n;j++)
                        d[i][j]=lck_min(d[i][j],d[i][k]+d[k][j]);
                k++;
            }
            if(d[x][y]==INF||t[x]>z||t[y]>z) out(-1),putchar('
    ');
            else out(d[x][y]),putchar('
    ');
        }
    return 0;
    }
  • 相关阅读:
    tar打包如何不打包某一个文件夹(排除某些文件夹)
    第一个SpringBoot应用
    Linux(以RHEL7为例)下添加工作区的方法|| The Way To Add Workspace On Linux
    Linux(以centos7为例)下自动挂载NTFS硬盘
    基于Moodle的IT课程辅助教育平台搭建
    搭建基于python +opencv+Beautifulsoup+Neurolab机器学习平台
    如何利用word2013写图文并茂的博客
    如何安装win10+Red Hat Enterprise Linux双系统?
    课堂练习:ex 4-20
    实验二 函数重载、函数模板、简单类的定义和实现
  • 原文地址:https://www.cnblogs.com/lck-lck/p/9850156.html
Copyright © 2020-2023  润新知