洛谷P1119|灾后重建|最短路|Floyd|Floyd的拓展

题目描述

1436945-20181108214917611-977706057.png

分析

考虑本题:
只通过修好的前几个村庄,从i->j的最短路,联想到
Flyod算法:
初始化:

f[][]=INF;
f[i][i]=0; 
for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);

考虑FLyod算法意义:
k为中转点,i为起点,j为终点
起点i->j如果只经过前k个点的最短距离
考虑本题:
因为只能经过修好的前几个村庄,则刚好对应了Floyd算法的k的意义。
因为询问的t是递增的,所以不用进行排序。
数据结构:
利用了类似栈的思想(程序里面的head实质上是tail):
因为t(包括每个村庄和询问)全是递增的,所以直接用栈首表示当前的时间的下标,如果当前下标的时间小于询问时间,则将中间断点增加一个

代码

#include <cstdio>
#include <iostream>
using namespace std;
const int maxn=205;
const int INF=9999999;
int n,m;
int dist[maxn][maxn],ct[maxn]/*完成的时间*/;
int head=0/*表示前head个村庄重建*/;
void init(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++) scanf("%d",&ct[i]);
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++) dist[i][j]=INF;
    for(int i=0;i<n;i++) dist[i][i]=0;
    for(int i=1;i<=m;i++){
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        dist[u][v]=dist[v][u]=w;
    }
}
void Floyd(int k){
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            dist[i][j]=dist[j][i]=min(dist[i][j],dist[i][k]+dist[k][j]);
}
void solve(){
    int q;scanf("%d",&q);
    while(q--){
        int u,v,t;scanf("%d%d%d",&u,&v,&t);
        while(ct[head]<=t&&head<n){//当前的时间足以让下一个修路 
            Floyd(head);
            head++;
        }
        if(ct[u]>t||ct[v]>t) printf("%d\n",-1);
        else printf("%d\n",dist[u][v]==INF?-1:dist[u][v]);
    }
}
int main(){
    init();
    solve();
    return 0;
}

转载于:https://www.cnblogs.com/saitoasuka/p/9931574.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值