zoukankan      html  css  js  c++  java
  • P1119 灾后重建(floyd进阶)

    思路:这道题看n的范围很小(n<=200),显然就用floyd可以解决的问题,但又并不是简单的floyd算法,还是需要一些小小的变化。一开始我的思路是先跑一次弗洛伊德最短路,这样子显然复杂度很高,并且题目中的路径长度是时刻可能更新的,所以我们应该在修建的时候再跑最短路。可以用一个变量来记录修改的点,这样子就可以大幅度的优化。

    代码如下

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1010;
    const int N=250;
    int n,m,x,y,v,T;
    int t[maxn];
    int f[N][N];
    int flag[N][N];
    int xx,yy,tt;
    int start;//动态变化的那个点
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&t[i]);
            f[i][i]=0;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                f[i][j]=1e9;
            }
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&v);
            f[x][y]=f[y][x]=v;
        }
        scanf("%d",&T);
        for(int o=1;o<=T;o++)
        {
            start=0;//Tle原因
            scanf("%d%d%d",&xx,&yy,&tt);
            while(t[start]<=tt&&start<n)
            {
                for(int i=0;i<n;i++)
                {
                    for(int j=0;j<n;j++)
                    {
                        f[i][j]=min(f[i][start]+f[start][j],f[i][j]);
                    }
                }
                start++;
            }
            if(f[xx][yy]==1e9||t[xx]>tt||t[yy]>tt)
            {
                printf("-1
    ");
            }
            else
            {
                printf("%d
    ",f[xx][yy]);
            }
        }
        return 0;
    }

    等等,但这样似乎只有30分,吸氧50 ,T了7个点

    究其原因,是因为每次跑弗洛伊德的时候,start都是又从零开始枚举的,这样显然是没有必要的

    所以我们就将他简单改一下

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1010;
    const int N=250;
    int n,m,x,y,v,T;
    int t[maxn];
    int f[N][N];
    int flag[N][N];
    int xx,yy,tt;
    int start;
    int Read(){
        int X = 0 ; char ch = getchar() ;
        while(ch > '9' || ch < '0') ch = getchar() ;
        while(ch >= '0' && ch <= '9')
        X = (X << 1) + (X << 3) + (ch ^ 48), ch = getchar() ;
        return X ;
    }
    int main()
    {
        n=Read(),m=Read();
        for(int i=0;i<n;i++)
        {
            t[i]=Read();
            f[i][i]=0;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                f[i][j]=1e9;
            }
        }
        for(int i=1;i<=m;i++)
        {
            x=Read();
            y=Read();
            v=Read();
            f[x][y]=f[y][x]=v;
        }
        T=Read();
        for(int o=1;o<=T;o++)
        {
            xx=Read(),yy=Read(),tt=Read();
            while(t[start]<=tt&&start<n)
            {
                for(int i=0;i<n;i++)
                {
                    for(int j=0;j<n;j++)
                    {
                        f[i][j]=min(f[i][start]+f[start][j],f[i][j]);
                    }
                }
                start++;
            }
            if(f[xx][yy]==1e9||t[xx]>tt||t[yy]>tt)
            {
                printf("-1
    ");
            }
            else
            {
                printf("%d
    ",f[xx][yy]);
            }
        }
        return 0;
    }

    因为修建的时候那个点都是一遍更新的,并且时间是单调递增的

    所以只需要更新一遍就得了,那个动态的点就不用再次清零了。

  • 相关阅读:
    信息安全系统设计基础第五周学习总结
    信息安全系统设计基础第四周学习总结
    信息安全系统设计基础第三周学习总结
    信息安全系统设计基础第二周学习总结
    信息安全系统设计基础第一周学习总结
    20135239益西拉姆第四次实验报告
    第三次实验报告 敏捷开发与XP实践
    20135239益西拉姆第二次实验报告
    20135239 第一次实验报告
    微信公众号方法(不定时更新)
  • 原文地址:https://www.cnblogs.com/LJB666/p/10665886.html
Copyright © 2011-2022 走看看