P1119 灾后重建

  第一眼看这道题感觉能很快切掉,但是后来才发现原来……

  这么坑……

  一开始,每一次重头开始计算并且dis和g互相赋值,浪费了很多时间,就只有30分,所以第二次就每一次记录last值域(就是上一次Floyd枚举到了那个点),再往后更新。但是只是有问题的,因为Floyd属于动态规划,必须要每次从头来找,这样才能保证更新到所有情况。

  所以第三次我就就每一次记录last值,但是还是从0到last枚举,又变成0分了……

  因为我每一次加入一个点,那么必须看这个点对所有的点是否有贡献,以后还可能会用到这个贡献之后的值。

  改之后40分……

  因为每一次会连着到n一起更新,而有的那个点是到不了的但是被赋值了(因为输出-1条件是dis[x][y]是否为-1)……需要一个vis判断是否到过。

  改了之后就AC了qwq

  代码如下:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define maxn 1010
#define INF 99999999
int dis[maxn][maxn],g[maxn][maxn],n,m,q,ok[maxn],vis[maxn];
int last=0;
void Floyd(int t)
{
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
        {
            g[i][j]=min(g[i][t]+g[t][j],g[i][j]);
            dis[i][j]=min(dis[i][j],g[i][j]);
            g[i][j]=dis[i][j];
        }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
        {
            dis[i][j]=g[i][j]=INF;
            if(i==j)
                dis[i][j]=g[i][j]=0;
        }
    for(int i=0; i<n; i++)
        scanf("%d",&ok[i]);
    for(int i=0; i<m; i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        g[x][y]=z;
        g[y][x]=z;
    }
    scanf("%d",&q);
    while(q--)
    {
        int x,y,t;
        scanf("%d%d%d",&x,&y,&t);
        for(; t>=ok[last]&&last<n; last++)
        {
            vis[last]=1;
            Floyd(last);
        }
        if(dis[x][y]==INF||!vis[x]||!vis[y])
        {
            printf("-1\n");
            continue;
        }
        else
            printf("%d\n",dis[x][y]);
    }
    return 0;
}

 

posted @ 2018-12-07 16:23  paopo  阅读(130)  评论(0)    收藏  举报