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


    题目描述

    分析

    考虑本题:
    只通过修好的前几个村庄,从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
    ",-1);
    		else printf("%d
    ",dist[u][v]==INF?-1:dist[u][v]);
    	}
    }
    int main(){
    	init();
    	solve();
    	return 0;
    }
    
    
  • 相关阅读:
    个人介绍
    实验三
    第二次实验
    实验一
    ATM管理系统
    第二次作业
    实验四 决策树算法及应用
    实验三 朴素贝叶斯算法及应用
    实验二 K-近邻算法及应用
    实验一 感知器及其应用
  • 原文地址:https://www.cnblogs.com/saitoasuka/p/9931574.html
Copyright © 2020-2023  润新知