P1119 灾后重建 题解
__vector__ · · 个人记录
\color{green}\text{AC算法:} floyd
题目描述
有
有
题目分析:
观察一下数据范围,
可以用一个结构体
解题过程
读入完成后,就是刚才说的将
对于每一组询问,可以依次遍历
想一想优化,这时候就可以利用每组询问的
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f = -1;
ch = getchar();
}
while(ch>='0'&&ch<='9'){
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
int n,m;
int dis[205][205];//距离,邻接矩阵
bool vis[205];//判断是否已经有了答案
int q;
struct Node{
int u, t, time;
int bh;
int ans;
}node[50005];
struct Czok{
int bh;//它的编号
int time;//修复时间
}czok[205];
bool cmp(Node a,Node b){
return a.time < b.time;
}
bool cmpbh(Node a,Node b){
return a.bh < b.bh;
}
inline void floyd(int mid){
for (int i = 1; i <= n;i++){
for (int j = 1; j <= n;j++){
dis[i][j]=min(dis[i][j],dis[i][mid]+dis[mid][j]);
}
}
}
int main(){
memset(dis, 0x3f, sizeof(dis));
n = read();
m = read();
for (int i = 1; i <= n;i++){
dis[i][i] = 0;
}
for (int i = 1; i <= n; i++){
czok[i].time = read();
czok[i].bh = i;
}
for (int i = 1; i <= m; i++)
{
int u, t, v;
u = read();
t = read();
v = read();
u++;//因为题目中起点是由0开始的,这里使用下标1,所以下标++
t++;
dis[u][t] = min(dis[u][t],v);//重边保留最小
dis[t][u] = min(dis[t][u], v);
}
q = read();
for (int i = 1; i <= q;i++){
int u, t, time;
u = read();
t = read();
time = read();
u++;//原理同上
t++;
node[i].bh=i;
node[i].u = u;
node[i].t = t;
node[i].time = time;
}
sort(node + 1, node + q + 1, cmp);
int pos = 1;//遍历所有村庄,遇到修复的就跑一边floyd
for (int i = 1; i <= q;i++)
{
while(czok[pos].time<=node[i].time&&pos<=n){
//如果已经修复完成,并且没有越界,跑一边floyd
int bh=czok[pos].bh;
floyd(bh);
vis[bh] = 1;
pos++;
}
if(!vis[node[i].u]||!vis[node[i].t]||dis[node[i].u][node[i].t]>100000000)
node[i].ans = -1;
else
node[i].ans = dis[node[i].u][node[i].t];
}
sort(node + 1, node + q + 1, cmpbh);
for (int i = 1; i <= q;i++){
cout << node[i].ans << endl;
}
return 0;
}