floyd是根据中转点进行的dp,因为这道题输入数据是递增的,所以套floyd板子就行
先正常地给整张图初始化成无穷大,用邻接矩阵存两村庄的边长
每次输入天数之后,用天数来更新重建完成的村庄的数量,用重建完成的村庄作为中转点做floyd
因为输入的天数是递增或不变的,所以整体来看就是从1号村庄向最新重建完成的村庄进行dp,不断地更新
#include <bits/stdc++.h>
using namespace std;
int M,N,Q;
int t[205]; //存储重建时间
int dist[205][205]; //存公路长度
void floyd(int k) //以前k个村庄为中转点进行dp
{
for(int i = 0; i < N; i ++)
{
for(int j = 0; j < N; j ++)
{
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
return;
}
int main()
{
cin >> N >> M; //村庄数和公路数
for(int i = 0; i < N; i ++) cin >> t[i];
for(int i = 0; i < N; i ++)
{
for(int j = 0 ;j < N; j ++)
if(i != j)dist[i][j]=0x3f3f3f; //给两个村庄之间的边长初始化成无穷大
}
for(int i = 0; i < M; i ++) //用邻接矩阵来存边
{
int a,b,c;
cin >> a >> b >> c;
dist[a][b] = c;
dist[b][a] = c;
}
cin >> Q; //询问次数
int temp = 0; //代表能访问到的序号最大的村庄
for(int i = 1; i <= Q; i ++)
{
int a,b,c;
cin >> a >> b >> c;
while(temp < N && t[temp] <= c) //如果这天村庄已经重建好了,并且村庄序号没有越界
{
floyd(temp++); //以前temp个村庄作为中转点
}
if(c < t[a] || c < t[b]) cout << -1; //没重建好直接GG
else if(dist[a][b] == 0x3f3f3f) cout << -1; //两村庄不连通也直接GG
else cout << dist[a][b];
if(i != Q) cout << endl;
}
return 0;
}