小白进阶之路-Luogu P1119

看完题目思索一会,发觉自己想了个假算法(但居然只能过样例,一定是自定义的三元祖很憨批) 就是每次把查询按时间排序,然后逐渐加入可以加入的边,跑Dijkstra,很明显,WA了8个,TLE了两个,被自己蠢怕了。

看了题解就会发现,Floyed已经攻占了题解区。

其实也不难理解,就是在不断更新可以使用维护的边去更新最短路的值(脑子短路的我没有看到关于时间t的输入都是不下降的。。。,还一直在想要不要排序) Folyed本身就是n遍利用第i个点更新其他路径,这个题就可以用更新的点,去维护最短路。

题目链接:Here


int t[202],n,m;
int dp[202][202];

int cnt = 0;


inline void update(int k) { // 利用当前加进来的点去维护最短路
    for(int i = 0;i < n;++i) {
        for(int j = 0;j < n;++j) {
            if(dp[i][j] > dp[i][k] + dp[k][j]) {
                dp[i][j] = dp[j][i] = dp[i][k] + dp[k][j];
            }
        }
    }
}

void solve() {
    int st,ed,tt;
    scanf("%d%d%d",&st,&ed,&tt);
    while(t[cnt] <= tt && cnt < n) {
        update(cnt);
        ++cnt;
    }
    if(t[st] > tt || t[ed] > tt) {
        printf("-1\n");return ;
    }else {
        if(dp[st][ed] == inf) printf("-1\n");
        else printf("%d\n",dp[st][ed]);
    }
}

int main() {
    for(int i = 0;i <= 200;++i){
        for(int j = 0;j <= 200;++j) {
            if(i == j) dp[i][j] = 0;
            else dp[i][j] = inf; // inf == 0x3f3f3f3f
        }
    }
    scanf("%d%d", &n,&m);
    for(int i = 0;i < n;++i) scanf("%d", &t[i]);
    for(int i = 0;i < m;++i){
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        dp[u][v] = w; // 好吧,我刚开始也没看到是双向边,我个憨憨
        dp[v][u] = w;
    }
    int k;scanf("%d",&k);
    while(k--) solve();
    return 0;
}


posted @ 2021-04-07 23:06  Wise_4  阅读(58)  评论(0编辑  收藏  举报